Skip to content

Commit fddd785

Browse files
authored
Merge branch 'dev' into feature/TPT-4109-python-sdk-support-regions-vpc-availability-endpoints
2 parents 9dbab80 + 42ca199 commit fddd785

File tree

8 files changed

+96
-13
lines changed

8 files changed

+96
-13
lines changed

linode_api4/objects/linode.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import copy
22
import string
33
import sys
4+
import warnings
45
from dataclasses import dataclass, field
56
from datetime import datetime
67
from enum import Enum
@@ -217,7 +218,7 @@ def resize(self, new_size):
217218
class Kernel(Base):
218219
"""
219220
The primary component of every Linux system. The kernel interfaces
220-
with the system’s hardware and it controls the operating system’s core functionality.
221+
with the system’s hardware, and it controls the operating system’s core functionality.
221222
222223
Your Compute Instance is capable of running one of three kinds of kernels:
223224
@@ -237,6 +238,10 @@ class Kernel(Base):
237238
to compile the kernel from source than to download it from your package manager. For more
238239
information on custom compiled kernels, review our guides for Debian, Ubuntu, and CentOS.
239240
241+
.. note::
242+
The ``xen`` property is deprecated and is no longer returned by the API.
243+
It is maintained for backward compatibility only.
244+
240245
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-kernel
241246
"""
242247

@@ -256,6 +261,16 @@ class Kernel(Base):
256261
"pvops": Property(),
257262
}
258263

264+
def __getattribute__(self, name: str) -> object:
265+
if name == "xen":
266+
warnings.warn(
267+
"The 'xen' property of Kernel is deprecated and is no longer "
268+
"returned by the API. It is maintained for backward compatibility only.",
269+
DeprecationWarning,
270+
stacklevel=2,
271+
)
272+
return super().__getattribute__(name)
273+
259274

260275
class Type(Base):
261276
"""

linode_api4/objects/monitor.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,19 @@ class DashboardType(StrEnum):
116116
custom = "custom"
117117

118118

119+
class AlertStatus(StrEnum):
120+
"""
121+
Enum for supported alert status values.
122+
"""
123+
124+
AlertDefinitionStatusProvisioning = "provisioning"
125+
AlertDefinitionStatusEnabling = "enabling"
126+
AlertDefinitionStatusDisabling = "disabling"
127+
AlertDefinitionStatusEnabled = "enabled"
128+
AlertDefinitionStatusDisabled = "disabled"
129+
AlertDefinitionStatusFailed = "failed"
130+
131+
119132
@dataclass
120133
class Filter(JSONObject):
121134
"""
@@ -428,6 +441,40 @@ class ChannelContent(JSONObject):
428441
# Other channel types like 'webhook', 'slack' could be added here as Optional fields.
429442

430443

444+
@dataclass
445+
class EmailDetails(JSONObject):
446+
"""
447+
Represents email-specific details for an alert channel.
448+
"""
449+
450+
usernames: Optional[List[str]] = None
451+
recipient_type: Optional[str] = None
452+
453+
454+
@dataclass
455+
class ChannelDetails(JSONObject):
456+
"""
457+
Represents the details block for an AlertChannel, which varies by channel type.
458+
"""
459+
460+
email: Optional[EmailDetails] = None
461+
462+
463+
@dataclass
464+
class AlertInfo(JSONObject):
465+
"""
466+
Represents a reference to alerts associated with an alert channel.
467+
Fields:
468+
- url: str - API URL to fetch the alerts for this channel
469+
- type: str - Type identifier (e.g., 'alerts-definitions')
470+
- alert_count: int - Number of alerts associated with this channel
471+
"""
472+
473+
url: str = ""
474+
_type: str = field(default="", metadata={"json_key": "type"})
475+
alert_count: int = 0
476+
477+
431478
class AlertChannel(Base):
432479
"""
433480
Represents an alert channel used to deliver notifications when alerts
@@ -450,7 +497,8 @@ class AlertChannel(Base):
450497
"label": Property(),
451498
"type": Property(),
452499
"channel_type": Property(),
453-
"alerts": Property(mutable=False, json_object=Alerts),
500+
"details": Property(mutable=False, json_object=ChannelDetails),
501+
"alerts": Property(mutable=False, json_object=AlertInfo),
454502
"content": Property(mutable=False, json_object=ChannelContent),
455503
"created": Property(is_datetime=True),
456504
"updated": Property(is_datetime=True),

test/integration/models/account/test_account.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import time
22
from datetime import datetime
33
from test.integration.conftest import get_region
4-
from test.integration.helpers import get_test_label, retry_sending_request
4+
from test.integration.helpers import (
5+
get_test_label,
6+
retry_sending_request,
7+
wait_for_condition,
8+
)
59

610
import pytest
711

@@ -102,13 +106,18 @@ def test_latest_get_event(test_linode_client, e2e_test_firewall):
102106
firewall=e2e_test_firewall,
103107
)
104108

105-
events = client.load(Event, "")
109+
def get_linode_status():
110+
return linode.status == "running"
106111

107-
latest_events = events._raw_json.get("data")
112+
# To ensure the Linode is running and the 'event' key has been populated
113+
wait_for_condition(3, 100, get_linode_status)
114+
115+
events = client.load(Event, "")
116+
latest_events = events._raw_json.get("data")[:15]
108117

109118
linode.delete()
110119

111-
for event in latest_events[:15]:
120+
for event in latest_events:
112121
if label == event["entity"]["label"]:
113122
break
114123
else:

test/integration/models/domain/test_domain.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ def test_clone(test_linode_client, test_domain):
4343
dom = "example.clone-" + timestamp + "-inttestsdk.org"
4444
domain.clone(dom)
4545

46-
ds = test_linode_client.domains()
47-
4846
time.sleep(1)
4947

48+
ds = test_linode_client.domains()
49+
5050
domains = [i.domain for i in ds]
5151

5252
assert dom in domains

test/integration/models/linode/test_linode.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,12 @@ def test_linode_initate_migration(test_linode_client, e2e_test_firewall):
611611
migration_type=MigrationType.COLD,
612612
)
613613

614+
def get_linode_status():
615+
return linode.status == "offline"
616+
617+
# To verify that Linode's status changed before deletion (during migration status is set to 'offline')
618+
wait_for_condition(5, 120, get_linode_status)
619+
614620
res = linode.delete()
615621

616622
assert res

test/integration/models/monitor/test_monitor.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
MonitorService,
1717
MonitorServiceToken,
1818
)
19+
from linode_api4.objects.monitor import AlertStatus
1920

2021

2122
# List all dashboards
@@ -227,7 +228,8 @@ def wait_for_alert_ready(alert_id, service_type: str):
227228
interval = initial_timeout
228229
alert = client.load(AlertDefinition, alert_id, service_type)
229230
while (
230-
getattr(alert, "status", None) == "in progress"
231+
getattr(alert, "status", None)
232+
!= AlertStatus.AlertDefinitionStatusEnabled
231233
and (time.time() - start) < timeout
232234
):
233235
time.sleep(interval)

test/integration/models/networking/test_networking.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
)
3333

3434

35-
def create_linode(test_linode_client):
35+
def create_linode_func(test_linode_client):
3636
client = test_linode_client
3737

3838
label = get_test_label()
@@ -49,7 +49,7 @@ def create_linode(test_linode_client):
4949

5050
@pytest.fixture
5151
def create_linode_for_ip_share(test_linode_client):
52-
linode = create_linode(test_linode_client)
52+
linode = create_linode_func(test_linode_client)
5353

5454
yield linode
5555

@@ -58,7 +58,7 @@ def create_linode_for_ip_share(test_linode_client):
5858

5959
@pytest.fixture
6060
def create_linode_to_be_shared_with_ips(test_linode_client):
61-
linode = create_linode(test_linode_client)
61+
linode = create_linode_func(test_linode_client)
6262

6363
yield linode
6464

@@ -302,6 +302,8 @@ def test_create_and_delete_vlan(test_linode_client, linode_for_vlan_tests):
302302
wait_for_condition(3, 100, get_status, linode, "rebooting")
303303
assert linode.status == "rebooting"
304304

305+
wait_for_condition(3, 100, get_status, linode, "running")
306+
305307
# Delete the VLAN
306308
is_deleted = test_linode_client.networking.delete_vlan(
307309
vlan_label, linode.region
@@ -334,6 +336,7 @@ def test_get_global_firewall_settings(test_linode_client):
334336

335337
def test_ip_info(test_linode_client, create_linode):
336338
linode = create_linode
339+
wait_for_condition(3, 100, get_status, linode, "running")
337340

338341
ip_info = test_linode_client.load(IPAddress, linode.ipv4[0])
339342

test/integration/models/nodebalancer/test_nodebalancer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def test_get_nb_config_with_udp(test_linode_client, create_nb_config_with_udp):
130130

131131
assert "udp" == config.protocol
132132
assert 1234 == config.udp_check_port
133-
assert 16 == config.udp_session_timeout
133+
assert 2 == config.udp_session_timeout
134134

135135

136136
def test_update_nb_config(test_linode_client, create_nb_config_with_udp):

0 commit comments

Comments
 (0)