Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
63bb91b
Add destination API models for monitor objects
sjer-akamai Apr 13, 2026
be7d021
Add destination API support in monitor group
sjer-akamai Apr 13, 2026
66aa467
Destination.history client call fix
sjer-akamai Apr 14, 2026
c6dbb16
`access_key_secret` parameter name fixes
sjer-akamai Apr 14, 2026
297a080
Add unit tests
sjer-akamai Apr 14, 2026
0f58fd6
Rename Destination to LogsDestination
sjer-akamai Apr 15, 2026
5a05955
Add integration tests
sjer-akamai Apr 15, 2026
f20535a
Typo fix
sjer-akamai Apr 16, 2026
e220822
Integration tests tweaks
sjer-akamai Apr 16, 2026
f275874
Documentation tweaks
sjer-akamai Apr 16, 2026
5e6be84
Add negative integration test cases
sjer-akamai Apr 17, 2026
df5f8c7
Fix assertion
sjer-akamai Apr 21, 2026
cf5c2e2
Formatting tweaks
sjer-akamai Apr 21, 2026
e70a0e6
ACLP Logs stream - add model and group
sjer-akamai Apr 21, 2026
c6f5331
ACLP Logs Stream - unit tests
sjer-akamai Apr 21, 2026
aaa7aea
ACLP Logs stream - add integration tests
sjer-akamai Apr 21, 2026
da52b00
ACLP Logs Stream - ensure update reverts on failed assertions
sjer-akamai Apr 21, 2026
7544892
ACLP Logs Stream - Formatting tweaks
sjer-akamai Apr 21, 2026
76a62af
ACLP Logs Stream - copilot review tweaks
sjer-akamai Apr 21, 2026
2b53808
ACLP Logs Stream - review tweaks - pt. 2
sjer-akamai Apr 21, 2026
e0d650f
ACLP Logs Stream - review tweaks - pt. 3
sjer-akamai Apr 22, 2026
0326e3e
ACLP Logs Stream - remove redundant comma
sjer-akamai Apr 22, 2026
3b13cec
ACLP Logs Stream - Merge save() method integration tests, add skip gu…
sjer-akamai Apr 22, 2026
05b299e
Update test/unit/objects/monitor_test.py
sjer-akamai Apr 23, 2026
2549bf0
ACLP Logs Stream - refactor invalid destination test to use session-s…
sjer-akamai Apr 23, 2026
ef7c13a
ACLP Logs - update assertion - stream status not tracked by version h…
sjer-akamai Apr 23, 2026
2d4a217
ACLP Logs - update e2e tests workflow
sjer-akamai Apr 23, 2026
dd0df03
Update .github/workflows/e2e-test.yml
sjer-akamai Apr 24, 2026
b1f7ea0
Update linode_api4/objects/monitor.py
sjer-akamai Apr 24, 2026
cdf2c04
ACLP Logs - Clarify LogsDestinationType supporting only one value
sjer-akamai Apr 24, 2026
bf57354
ACLP Logs - Fix formatting
sjer-akamai Apr 30, 2026
29fe847
ACLP Logs - Extend destination API with new updates
sjer-akamai May 4, 2026
7836172
ACLP Logs - Extend Stream API with lke_audit_logs_type, reorder tests
sjer-akamai May 4, 2026
a973cdf
ACLP Logs - fix __all__ statement
sjer-akamai May 4, 2026
e12157d
ACLP Logs - Stabilize stream tests
sjer-akamai May 5, 2026
9c190c0
ACLP Logs - Reduce integration tests runtime - remove unnecessary upd…
sjer-akamai May 5, 2026
4cc8da9
Merge branch 'dev' into ACLP-logs-support
sjer-akamai May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/e2e-test-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ on:
pull_request:
workflow_dispatch:
inputs:
run_aclp_logs_stream_tests:
description: 'Set this parameter to "true" to run ACLP logs stream related test cases'
required: false
default: 'false'
type: choice
options:
- 'true'
- 'false'
run_db_fork_tests:
description: 'Set this parameter to "true" to run fork database related test cases'
required: false
Expand Down Expand Up @@ -104,7 +112,7 @@ jobs:
run: |
timestamp=$(date +'%Y%m%d%H%M')
report_filename="${timestamp}_sdk_test_report.xml"
make test-int RUN_DB_FORK_TESTS=${{ github.event.inputs.run_db_fork_tests }} RUN_DB_TESTS=${{ github.event.inputs.run_db_tests }} TEST_ARGS="--junitxml=${report_filename}" TEST_SUITE="${{ github.event.inputs.test_suite }}"
make test-int RUN_DB_FORK_TESTS=${{ github.event.inputs.run_db_fork_tests }} RUN_DB_TESTS=${{ github.event.inputs.run_db_tests }} RUN_ACLP_LOGS_STREAM_TESTS=${{ github.event.inputs.run_aclp_logs_stream_tests }} TEST_ARGS="--junitxml=${report_filename}" TEST_SUITE="${{ github.event.inputs.test_suite }}"
env:
LINODE_TOKEN: ${{ secrets.LINODE_TOKEN }}

Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ name: Integration Tests
on:
workflow_dispatch:
inputs:
run_aclp_logs_stream_tests:
description: 'Set this parameter to "true" to run ACLP logs stream related test cases'
required: false
default: 'false'
type: choice
options:
- 'true'
- 'false'
run_db_fork_tests:
description: 'Set this parameter to "true" to run fork database related test cases'
required: false
Expand Down Expand Up @@ -99,7 +107,7 @@ jobs:
run: |
timestamp=$(date +'%Y%m%d%H%M')
report_filename="${timestamp}_sdk_test_report.xml"
make test-int RUN_DB_FORK_TESTS=${{ github.event.inputs.run_db_fork_tests }} RUN_DB_TESTS=${{ github.event.inputs.run_db_tests }} TEST_SUITE="${{ github.event.inputs.test_suite }}" TEST_ARGS="--junitxml=${report_filename}"
make test-int RUN_DB_FORK_TESTS=${{ github.event.inputs.run_db_fork_tests }} RUN_DB_TESTS=${{ github.event.inputs.run_db_tests }} RUN_ACLP_LOGS_STREAM_TESTS=${{ github.event.inputs.run_aclp_logs_stream_tests }} TEST_SUITE="${{ github.event.inputs.test_suite }}" TEST_ARGS="--junitxml=${report_filename}"
env:
LINODE_TOKEN: ${{ env.LINODE_TOKEN }}

Expand Down
213 changes: 213 additions & 0 deletions linode_api4/groups/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@
AlertDefinition,
AlertDefinitionEntity,
AlertScope,
LogsDestination,
LogsDestinationType,
LogsStream,
LogsStreamStatus,
LogsStreamType,
MonitorDashboard,
MonitorMetricsDefinition,
MonitorService,
MonitorServiceToken,
)
from linode_api4.objects.monitor import (
AkamaiObjectStorageLogsDestinationDetails,
CustomHTTPSLogsDestinationDetails,
LogsStreamDetails,
)

__all__ = [
"MonitorGroup",
Expand Down Expand Up @@ -332,3 +342,206 @@ def alert_definition_entities(
*filters,
endpoint=endpoint,
)

def destinations(self, *filters) -> PaginatedList:
"""
List available logs destinations.

Returns a paginated collection of :class:`LogsDestination` objects which
describe logs destinations. By default, this method returns all available
destinations; you can supply optional filter expressions to restrict
the results, for example::

# Get destinations created by username and with id 111
destinations = client.monitor.destinations(LogsDestination.created_by == "username",
LogsDestination.id == 111)

API Documentation: https://techdocs.akamai.com/linode-api/reference/get-destinations

:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.

:returns: A list of :class:`LogsDestination` objects matching the query.
:rtype: PaginatedList of LogsDestination
"""

return self.client._get_and_filter(LogsDestination, *filters)

def destination_create(
self,
label: str,
type: Union[LogsDestinationType, str],
details: Union[
AkamaiObjectStorageLogsDestinationDetails,
CustomHTTPSLogsDestinationDetails,
],
) -> LogsDestination:
"""
Creates a new :any:`LogsDestination` for logs on this account.

For an ``akamai_object_storage`` destination::

client = LinodeClient(TOKEN)

new_destination = client.monitor.destination_create(
label="OBJ_logs_destination",
type="akamai_object_storage",
details=AkamaiObjectStorageLogsDestinationDetails(
access_key_id="1ABCD23EFG4HIJKLMNO5",
access_key_secret="1aB2CD3e4fgHi5JK6lmnop7qR8STU9VxYzabcdefHh",
bucket_name="primary-bucket",
host="primary-bucket-1.us-east-12.linodeobjects.com",
path="audit-logs",
)
)

For a ``custom_https`` destination::

new_destination = client.monitor.destination_create(
label="custom_logs_destination",
type="custom_https",
details=CustomHTTPSLogsDestinationDetails(
endpoint_url="https://my-site.com/log-storage/basicAuth",
authentication=DestinationAuthentication(
type="basic",
details=BasicAuthenticationDetails(
basic_authentication_user="user",
basic_authentication_password="pass",
),
),
data_compression="gzip",
content_type="application/json",
)
)

API Documentation: https://techdocs.akamai.com/linode-api/reference/post-destination

:param label: The name for this logs destination.
:type label: str
:param type: The type of destination — ``akamai_object_storage`` or ``custom_https``.
:type type: str or LogsDestinationType
:param details: A typed details object matching the destination type.
Use :class:`AkamaiObjectStorageLogsDestinationDetails` for
``akamai_object_storage`` or :class:`CustomHTTPSLogsDestinationDetails`
for ``custom_https``.
:type details: AkamaiObjectStorageLogsDestinationDetails or CustomHTTPSLogsDestinationDetails

:returns: The newly created logs destination.
:rtype: LogsDestination
"""

params = {
"label": label,
"type": type,
"details": details.dict,
}

result = self.client.post("/monitor/streams/destinations", data=params)

if "id" not in result:
raise UnexpectedResponseError(
"Unexpected response when creating destination!",
json=result,
)

return LogsDestination(self.client, result["id"], result)

def streams(self, *filters) -> PaginatedList:
"""
List available logs streams.

Returns a paginated collection of :class:`LogsStream` objects which
describe logs streams. By default, this method returns all available
streams; you can supply optional filter expressions to restrict
the results, for example::

# Get all streams with status ``provisioning``
provisioning_streams = client.monitor.streams(LogsStream.status == "provisioning")

API Documentation: https://techdocs.akamai.com/linode-api/reference/get-streams

:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.
:returns: A list of :class:`LogsStream` objects matching the query.
:rtype: PaginatedList of LogsStream
"""

return self.client._get_and_filter(LogsStream, *filters)

def stream_create(
self,
destinations: list[int],
label: str,
type: Union[LogsStreamType, str],
status: Optional[Union[LogsStreamStatus, str]] = None,
details: Optional[LogsStreamDetails] = None,
) -> LogsStream:
"""
Creates a new :any:`LogsStream` for logs on this account. For example::

client = LinodeClient(TOKEN)

# audit_logs stream (no details required)
new_stream = client.monitor.stream_create(
destinations=[1234],
label="Linode_services",
status="active",
type="audit_logs"
)

# lke_audit_logs stream with specific clusters
lke_stream = client.monitor.stream_create(
destinations=[1234],
label="LKE_audit_stream",
type="lke_audit_logs",
details=LogsStreamDetails(
cluster_ids=[1111, 2222],
is_auto_add_all_clusters_enabled=False,
)
)

API Documentation: https://techdocs.akamai.com/linode-api/reference/post-stream

:param destinations: The unique identifier for the sync point that will receive logs data.
Run the List destinations operation and store the id values for each applicable destination.
At the moment only single destination is supported.
:type destinations: list[int]
:param label: The name of the stream. This is used for display purposes in Akamai Cloud Manager.
:type label: str
:param type: The type of stream — ``audit_logs`` for Linode control plane logs,
or ``lke_audit_logs`` for LKE enterprise cluster audit logs.
:type type: str or LogsStreamType
:param status: (Optional) The availability status of the stream. Possible values are: ``active``, ``inactive``.
Defaults to ``active``.
:type status: str
:param details: (Optional) Additional stream details. Only applicable for
``lke_audit_logs`` streams. Omit for ``audit_logs`` streams.
:type details: LogsStreamDetails

:returns: The newly created logs stream.
:rtype: LogsStream
"""

params = {
"label": label,
"type": type,
"destinations": destinations,
}

if status is not None:
params["status"] = status

if details is not None:
params["details"] = details.dict

result = self.client.post("/monitor/streams", data=params)

if "id" not in result:
raise UnexpectedResponseError(
"Unexpected response when creating logs stream!",
json=result,
)

return LogsStream(self.client, result["id"], result)
Loading
Loading