Skip to content

Commit ef90a1c

Browse files
Merge branch 'dev' into proj/block-storage-volume-limit-increase
2 parents 42b0b9d + bc5f735 commit ef90a1c

File tree

12 files changed

+161
-16
lines changed

12 files changed

+161
-16
lines changed

.github/workflows/e2e-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ jobs:
193193
submodules: 'recursive'
194194

195195
- name: Download test report
196-
uses: actions/download-artifact@v7
196+
uses: actions/download-artifact@v8
197197
with:
198198
name: test-report-file
199199

.github/workflows/labeler.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
uses: actions/checkout@v6
2222
-
2323
name: Run Labeler
24-
uses: crazy-max/ghaction-github-labeler@24d110aa46a59976b8a7f35518cb7f14f434c916
24+
uses: crazy-max/ghaction-github-labeler@548a7c3603594ec17c819e1239f281a3b801ab4d
2525
with:
2626
github-token: ${{ secrets.GITHUB_TOKEN }}
2727
yaml-file: .github/labels.yml

linode_api4/objects/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .dbase import DerivedBase
44
from .serializable import JSONObject
55
from .filtering import and_, or_
6-
from .region import Region
6+
from .region import Region, Capability
77
from .image import Image
88
from .linode import *
99
from .linode_interfaces import *

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
@@ -220,7 +221,7 @@ def resize(self, new_size):
220221
class Kernel(Base):
221222
"""
222223
The primary component of every Linux system. The kernel interfaces
223-
with the system’s hardware and it controls the operating system’s core functionality.
224+
with the system’s hardware, and it controls the operating system’s core functionality.
224225
225226
Your Compute Instance is capable of running one of three kinds of kernels:
226227
@@ -240,6 +241,10 @@ class Kernel(Base):
240241
to compile the kernel from source than to download it from your package manager. For more
241242
information on custom compiled kernels, review our guides for Debian, Ubuntu, and CentOS.
242243
244+
.. note::
245+
The ``xen`` property is deprecated and is no longer returned by the API.
246+
It is maintained for backward compatibility only.
247+
243248
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-kernel
244249
"""
245250

@@ -259,6 +264,16 @@ class Kernel(Base):
259264
"pvops": Property(),
260265
}
261266

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

263278
class Type(Base):
264279
"""

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),

linode_api4/objects/region.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,68 @@
33

44
from linode_api4.errors import UnexpectedResponseError
55
from linode_api4.objects.base import Base, JSONObject, Property
6+
from linode_api4.objects.serializable import StrEnum
7+
8+
9+
class Capability(StrEnum):
10+
"""
11+
An enum class that represents the capabilities that Linode offers
12+
across different regions and services.
13+
14+
These capabilities indicate what services are available in each data center.
15+
"""
16+
17+
linodes = "Linodes"
18+
nodebalancers = "NodeBalancers"
19+
block_storage = "Block Storage"
20+
object_storage = "Object Storage"
21+
object_storage_regions = "Object Storage Access Key Regions"
22+
object_storage_endpoint_types = "Object Storage Endpoint Types"
23+
lke = "Kubernetes"
24+
lke_ha_controlplanes = "LKE HA Control Planes"
25+
lke_e = "Kubernetes Enterprise"
26+
firewall = "Cloud Firewall"
27+
gpu = "GPU Linodes"
28+
vlans = "Vlans"
29+
vpcs = "VPCs"
30+
vpcs_extra = "VPCs Extra"
31+
machine_images = "Machine Images"
32+
dbaas = "Managed Databases"
33+
dbaas_beta = "Managed Databases Beta"
34+
bs_migrations = "Block Storage Migrations"
35+
metadata = "Metadata"
36+
premium_plans = "Premium Plans"
37+
edge_plans = "Edge Plans"
38+
distributed_plans = "Distributed Plans"
39+
lke_control_plane_acl = "LKE Network Access Control List (IP ACL)"
40+
aclb = "Akamai Cloud Load Balancer"
41+
support_ticket_severity = "Support Ticket Severity"
42+
backups = "Backups"
43+
placement_group = "Placement Group"
44+
disk_encryption = "Disk Encryption"
45+
la_disk_encryption = "LA Disk Encryption"
46+
akamai_ram_protection = "Akamai RAM Protection"
47+
blockstorage_encryption = "Block Storage Encryption"
48+
blockstorage_perf_b1 = "Block Storage Performance B1"
49+
blockstorage_perf_b1_default = "Block Storage Performance B1 Default"
50+
aclp = "Akamai Cloud Pulse"
51+
aclp_logs = "Akamai Cloud Pulse Logs"
52+
aclp_logs_lkee = "Akamai Cloud Pulse Logs LKE-E Audit"
53+
aclp_logs_dc_lkee = "ACLP Logs Datacenter LKE-E"
54+
smtp_enabled = "SMTP Enabled"
55+
stackscripts = "StackScripts"
56+
vpu = "NETINT Quadra T1U"
57+
linode_interfaces = "Linode Interfaces"
58+
maintenance_policy = "Maintenance Policy"
59+
vpc_dual_stack = "VPC Dual Stack"
60+
vpc_ipv6_stack = "VPC IPv6 Stack"
61+
nlb = "Network LoadBalancer"
62+
natgateway = "NAT Gateway"
63+
lke_e_byovpc = "Kubernetes Enterprise BYO VPC"
64+
lke_e_stacktype = "Kubernetes Enterprise Dual Stack"
65+
ruleset = "Cloud Firewall Rule Set"
66+
prefixlists = "Cloud Firewall Prefix Lists"
67+
current_prefixlists = "Cloud Firewall Prefix List Current References"
668

769

870
@dataclass

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)

0 commit comments

Comments
 (0)