Skip to content

Commit d47b051

Browse files
committed
feat: deprecate datacenter in primary ips and servers
See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters
1 parent c314c8a commit d47b051

File tree

4 files changed

+109
-13
lines changed

4 files changed

+109
-13
lines changed

hcloud/primary_ips/client.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import warnings
34
from typing import TYPE_CHECKING, Any, NamedTuple
45

56
from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
@@ -9,6 +10,7 @@
910
if TYPE_CHECKING:
1011
from .._client import Client
1112
from ..datacenters import BoundDatacenter, Datacenter
13+
from ..locations import BoundLocation, Location
1214

1315

1416
class BoundPrimaryIP(BoundModelBase[PrimaryIP], PrimaryIP):
@@ -24,10 +26,15 @@ def __init__(
2426
):
2527
# pylint: disable=import-outside-toplevel
2628
from ..datacenters import BoundDatacenter
29+
from ..locations import BoundLocation
2730

28-
datacenter = data.get("datacenter", {})
29-
if datacenter:
30-
data["datacenter"] = BoundDatacenter(client._parent.datacenters, datacenter)
31+
raw = data.get("datacenter", {})
32+
if raw:
33+
data["datacenter"] = BoundDatacenter(client._parent.datacenters, raw)
34+
35+
raw = data.get("location", {})
36+
if raw:
37+
data["location"] = BoundLocation(client._parent.locations, raw)
3138

3239
super().__init__(client, data, complete)
3340

@@ -309,6 +316,7 @@ def create(
309316
type: str,
310317
name: str,
311318
datacenter: Datacenter | BoundDatacenter | None = None,
319+
location: Location | BoundLocation | None = None,
312320
assignee_type: str | None = "server",
313321
assignee_id: int | None = None,
314322
auto_delete: bool | None = False,
@@ -319,6 +327,7 @@ def create(
319327
:param type: str Primary IP type Choices: ipv4, ipv6
320328
:param name: str
321329
:param datacenter: Datacenter (optional)
330+
:param location: Location (optional)
322331
:param assignee_type: str (optional)
323332
:param assignee_id: int (optional)
324333
:param auto_delete: bool (optional)
@@ -333,7 +342,16 @@ def create(
333342
"auto_delete": auto_delete,
334343
}
335344
if datacenter is not None:
345+
warnings.warn(
346+
"The 'datacenter' argument is deprecated and will be removed after 1 July 2026. "
347+
"Please use the 'location' argument instead. "
348+
"See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters",
349+
DeprecationWarning,
350+
stacklevel=2,
351+
)
336352
data["datacenter"] = datacenter.id_or_name
353+
if location is not None:
354+
data["location"] = location.id_or_name
337355
if assignee_id is not None:
338356
data["assignee_id"] = assignee_id
339357
if labels is not None:

hcloud/primary_ips/domain.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from __future__ import annotations
22

3+
import warnings
34
from typing import TYPE_CHECKING, TypedDict
45

56
from ..core import BaseDomain, DomainIdentityMixin
67

78
if TYPE_CHECKING:
89
from ..actions import BoundAction
910
from ..datacenters import BoundDatacenter
11+
from ..locations import BoundLocation
1012
from ..rdns import DNSPtr
1113
from .client import BoundPrimaryIP
1214

@@ -24,6 +26,8 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin):
2426
Array of reverse DNS entries
2527
:param datacenter: :class:`Datacenter <hcloud.datacenters.client.BoundDatacenter>`
2628
Datacenter the Primary IP was created in.
29+
:param location: :class:`Location <hcloud.locations.client.BoundLocation>`
30+
Location the Primary IP was created in.
2731
:param blocked: boolean
2832
Whether the IP is blocked
2933
:param protection: dict
@@ -42,12 +46,11 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin):
4246
Delete the Primary IP when the Assignee it is assigned to is deleted.
4347
"""
4448

45-
__api_properties__ = (
49+
__properties__ = (
4650
"id",
4751
"ip",
4852
"type",
4953
"dns_ptr",
50-
"datacenter",
5154
"blocked",
5255
"protection",
5356
"labels",
@@ -57,7 +60,14 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin):
5760
"assignee_type",
5861
"auto_delete",
5962
)
60-
__slots__ = __api_properties__
63+
__api_properties__ = (
64+
*__properties__,
65+
"datacenter",
66+
)
67+
__slots__ = (
68+
*__properties__,
69+
"_datacenter",
70+
)
6171

6272
def __init__(
6373
self,
@@ -66,6 +76,7 @@ def __init__(
6676
ip: str | None = None,
6777
dns_ptr: list[DNSPtr] | None = None,
6878
datacenter: BoundDatacenter | None = None,
79+
location: BoundLocation | None = None,
6980
blocked: bool | None = None,
7081
protection: PrimaryIPProtection | None = None,
7182
labels: dict[str, str] | None = None,
@@ -80,6 +91,7 @@ def __init__(
8091
self.ip = ip
8192
self.dns_ptr = dns_ptr
8293
self.datacenter = datacenter
94+
self.location = location
8395
self.blocked = blocked
8496
self.protection = protection
8597
self.labels = labels
@@ -89,6 +101,27 @@ def __init__(
89101
self.assignee_type = assignee_type
90102
self.auto_delete = auto_delete
91103

104+
@property
105+
def datacenter(self) -> BoundDatacenter | None:
106+
"""
107+
Datacenter the Primary IP was created in.
108+
109+
.. deprecated:: 2.13
110+
See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters
111+
"""
112+
warnings.warn(
113+
"The 'datacenter' property is deprecated and will be removed after 1 July 2026. "
114+
"Please use the 'location' property instead. "
115+
"",
116+
DeprecationWarning,
117+
stacklevel=2,
118+
)
119+
return self._datacenter
120+
121+
@datacenter.setter
122+
def datacenter(self, value: BoundDatacenter | None) -> None:
123+
self._datacenter = value
124+
92125

93126
class PrimaryIPProtection(TypedDict):
94127
delete: bool

hcloud/servers/client.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import warnings
34
from datetime import datetime
45
from typing import TYPE_CHECKING, Any, NamedTuple
56

@@ -12,6 +13,7 @@
1213
from ..floating_ips import BoundFloatingIP
1314
from ..images import BoundImage, CreateImageResponse
1415
from ..isos import BoundIso
16+
from ..locations import BoundLocation, Location
1517
from ..metrics import Metrics
1618
from ..placement_groups import BoundPlacementGroup
1719
from ..primary_ips import BoundPrimaryIP
@@ -39,7 +41,6 @@
3941
from ..firewalls import Firewall
4042
from ..images import Image
4143
from ..isos import Iso
42-
from ..locations import BoundLocation, Location
4344
from ..networks import BoundNetwork, Network
4445
from ..placement_groups import PlacementGroup
4546
from ..server_types import ServerType
@@ -60,9 +61,13 @@ def __init__(
6061
data: dict[str, Any],
6162
complete: bool = True,
6263
):
63-
datacenter = data.get("datacenter")
64-
if datacenter is not None:
65-
data["datacenter"] = BoundDatacenter(client._parent.datacenters, datacenter)
64+
raw = data.get("datacenter")
65+
if raw:
66+
data["datacenter"] = BoundDatacenter(client._parent.datacenters, raw)
67+
68+
raw = data.get("location")
69+
if raw:
70+
data["location"] = BoundLocation(client._parent.locations, raw)
6671

6772
volumes = data.get("volumes", [])
6873
if volumes:
@@ -662,6 +667,13 @@ def create(
662667
if location is not None:
663668
data["location"] = location.id_or_name
664669
if datacenter is not None:
670+
warnings.warn(
671+
"The 'datacenter' argument is deprecated and will be removed after 1 July 2026. "
672+
"Please use the 'location' argument instead. "
673+
"See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters",
674+
DeprecationWarning,
675+
stacklevel=2,
676+
)
665677
data["datacenter"] = datacenter.id_or_name
666678
if ssh_keys is not None:
667679
data["ssh_keys"] = [ssh_key.id_or_name for ssh_key in ssh_keys]

hcloud/servers/domain.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import warnings
34
from typing import TYPE_CHECKING, Literal, TypedDict
45

56
from ..core import BaseDomain, DomainIdentityMixin
@@ -11,6 +12,7 @@
1112
from ..floating_ips import BoundFloatingIP
1213
from ..images import BoundImage
1314
from ..isos import BoundIso
15+
from ..locations import BoundLocation
1416
from ..metrics import Metrics
1517
from ..networks import BoundNetwork, Network
1618
from ..placement_groups import BoundPlacementGroup
@@ -36,6 +38,7 @@ class Server(BaseDomain, DomainIdentityMixin):
3638
Public network information.
3739
:param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
3840
:param datacenter: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
41+
:param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
3942
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>`, None
4043
:param iso: :class:`BoundIso <hcloud.isos.client.BoundIso>`, None
4144
:param rescue_enabled: bool
@@ -81,13 +84,13 @@ class Server(BaseDomain, DomainIdentityMixin):
8184
STATUS_UNKNOWN = "unknown"
8285
"""Server Status unknown"""
8386

84-
__api_properties__ = (
87+
__properties__ = (
8588
"id",
8689
"name",
8790
"status",
8891
"public_net",
8992
"server_type",
90-
"datacenter",
93+
"location",
9194
"image",
9295
"iso",
9396
"rescue_enabled",
@@ -104,7 +107,14 @@ class Server(BaseDomain, DomainIdentityMixin):
104107
"primary_disk_size",
105108
"placement_group",
106109
)
107-
__slots__ = __api_properties__
110+
__api_properties__ = (
111+
*__properties__,
112+
"datacenter",
113+
)
114+
__slots__ = (
115+
*__properties__,
116+
"_datacenter",
117+
)
108118

109119
# pylint: disable=too-many-locals
110120
def __init__(
@@ -116,6 +126,7 @@ def __init__(
116126
public_net: PublicNetwork | None = None,
117127
server_type: BoundServerType | None = None,
118128
datacenter: BoundDatacenter | None = None,
129+
location: BoundLocation | None = None,
119130
image: BoundImage | None = None,
120131
iso: BoundIso | None = None,
121132
rescue_enabled: bool | None = None,
@@ -138,6 +149,7 @@ def __init__(
138149
self.public_net = public_net
139150
self.server_type = server_type
140151
self.datacenter = datacenter
152+
self.location = location
141153
self.image = image
142154
self.iso = iso
143155
self.rescue_enabled = rescue_enabled
@@ -163,6 +175,27 @@ def private_net_for(self, network: BoundNetwork | Network) -> PrivateNet | None:
163175
return o
164176
return None
165177

178+
@property
179+
def datacenter(self) -> BoundDatacenter | None:
180+
"""
181+
Datacenter the Server was created in.
182+
183+
.. deprecated:: 2.13
184+
See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters
185+
"""
186+
warnings.warn(
187+
"The 'datacenter' property is deprecated and will be removed after 1 July 2026. "
188+
"Please use the 'location' property instead. "
189+
"See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters",
190+
DeprecationWarning,
191+
stacklevel=2,
192+
)
193+
return self._datacenter
194+
195+
@datacenter.setter
196+
def datacenter(self, value: BoundDatacenter | None) -> None:
197+
self._datacenter = value
198+
166199

167200
class ServerProtection(TypedDict):
168201
rebuild: bool

0 commit comments

Comments
 (0)