Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 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
b2de6cd
ACLP Logs - Clarify LogsDestinationType supporting only one value
sjer-akamai Apr 24, 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
182 changes: 182 additions & 0 deletions linode_api4/groups/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
MonitorMetricsDefinition,
MonitorService,
MonitorServiceToken,
LogsDestination,
LogsDestinationType,
LogsStream,
LogsStreamStatus,
LogsStreamType,
)

__all__ = [
Expand Down Expand Up @@ -332,3 +337,180 @@ 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],
access_key_id: str,
access_key_secret: str,
bucket_name: str,
host: str,
path: Optional[str] = None,
) -> LogsDestination:
"""
Creates a new :any:`LogsDestination` for logs on this account with
the given label, type, and object storage details. For example::

client = LinodeClient(TOKEN)

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

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 for logs data sync. Currently, only ``akamai_object_storage`` is supported for use.
:type type: str or LogsDestinationType
:param access_key_id: The unique identifier assigned to the Object Storage key required for authentication to the bucket.
:type access_key_id: str
:param access_key_secret: The Object Storage key's secret key.
:type access_key_secret: str
:param bucket_name: The name of the Object Storage bucket
:type bucket_name: str
:param host: The hostname where the Object Storage bucket can be accessed
:type host: str
:param path: (Optional) Custom path for log storage in your Object Storage bucket.
:type path: Optional[str]

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

params = {
"label": label,
"type": type,
"details": {
"access_key_id": access_key_id,
"access_key_secret": access_key_secret,
"bucket_name": bucket_name,
"host": host,
}
}

if path is not None:
params["details"]["path"] = path

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
) -> LogsStream:
"""
Creates a new :any:`LogsStream` for logs on this account with
the given label, type, and object storage details. For example::

client = LinodeClient(TOKEN)

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

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

:param destinations: List of unique identifiers for the sync points 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. Set this to ``audit_logs`` for logs consisting of all the control plane
operations for the services in your Linodes.
:type type: str
:param status: (Optional) The availability status of the stream. Possible values are: ``active``, ``inactive``.
Defaults to ``active``.
:type status: str

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

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

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

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