diff --git a/cloudfoundry_client/client.py b/cloudfoundry_client/client.py index f78180b..a4ecfe7 100644 --- a/cloudfoundry_client/client.py +++ b/cloudfoundry_client/client.py @@ -28,6 +28,7 @@ from cloudfoundry_client.v2.spaces import SpaceManager as SpaceManagerV2 from cloudfoundry_client.v3.apps import AppManager +from cloudfoundry_client.v3.audit_events import AuditEventManager from cloudfoundry_client.v3.buildpacks import BuildpackManager from cloudfoundry_client.v3.domains import DomainManager from cloudfoundry_client.v3.droplets import DropletManager @@ -119,6 +120,7 @@ class V3(object): def __init__(self, cloud_controller_v3_url: str, credential_manager: "CloudFoundryClient"): target_endpoint = cloud_controller_v3_url.removesuffix("/v3") self.apps = AppManager(target_endpoint, credential_manager) + self.audit_events = AuditEventManager(target_endpoint, credential_manager) self.buildpacks = BuildpackManager(target_endpoint, credential_manager) self.domains = DomainManager(target_endpoint, credential_manager) self.droplets = DropletManager(target_endpoint, credential_manager) diff --git a/cloudfoundry_client/v3/audit_events.py b/cloudfoundry_client/v3/audit_events.py new file mode 100644 index 0000000..aef9758 --- /dev/null +++ b/cloudfoundry_client/v3/audit_events.py @@ -0,0 +1,11 @@ +from typing import TYPE_CHECKING + +from cloudfoundry_client.v3.entities import EntityManager, Entity + +if TYPE_CHECKING: + from cloudfoundry_client.client import CloudFoundryClient + + +class AuditEventManager(EntityManager[Entity]): + def __init__(self, target_endpoint: str, client: "CloudFoundryClient"): + super().__init__(target_endpoint, client, "/v3/audit_events") diff --git a/tests/fixtures/v3/audit_events/GET_response.json b/tests/fixtures/v3/audit_events/GET_response.json new file mode 100644 index 0000000..23a01aa --- /dev/null +++ b/tests/fixtures/v3/audit_events/GET_response.json @@ -0,0 +1,48 @@ +{ + "pagination": { + "total_results": 1, + "total_pages": 1, + "first": { + "href": "https://api.example.org/v3/audit_events?page=1&per_page=2" + }, + "last": { + "href": "https://api.example.org/v3/audit_events?page=1&per_page=2" + }, + "next": null, + "previous": null + }, + "resources": [ + { + "guid": "a595fe2f-01ff-4965-a50c-290258ab8582", + "created_at": "2016-06-08T16:41:23Z", + "updated_at": "2016-06-08T16:41:26Z", + "type": "audit.app.update", + "actor": { + "guid": "d144abe3-3d7b-40d4-b63f-2584798d3ee5", + "type": "user", + "name": "admin" + }, + "target": { + "guid": "2e3151ba-9a63-4345-9c5b-6d8c238f4e55", + "type": "app", + "name": "my-app" + }, + "data": { + "request": { + "recursive": true + } + }, + "space": { + "guid": "cb97dd25-d4f7-4185-9e6f-ad6e585c207c" + }, + "organization": { + "guid": "d9be96f5-ea8f-4549-923f-bec882e32e3c" + }, + "links": { + "self": { + "href": "https://api.example.org//v3/audit_events/a595fe2f-01ff-4965-a50c-290258ab8582" + } + } + } + ] +} diff --git a/tests/fixtures/v3/audit_events/GET_{id}_response.json b/tests/fixtures/v3/audit_events/GET_{id}_response.json new file mode 100644 index 0000000..58b9e1a --- /dev/null +++ b/tests/fixtures/v3/audit_events/GET_{id}_response.json @@ -0,0 +1,32 @@ +{ + "guid": "a595fe2f-01ff-4965-a50c-290258ab8582", + "created_at": "2016-06-08T16:41:23Z", + "updated_at": "2016-06-08T16:41:26Z", + "type": "audit.app.update", + "actor": { + "guid": "d144abe3-3d7b-40d4-b63f-2584798d3ee5", + "type": "user", + "name": "admin" + }, + "target": { + "guid": "2e3151ba-9a63-4345-9c5b-6d8c238f4e55", + "type": "app", + "name": "my-app" + }, + "data": { + "request": { + "recursive": true + } + }, + "space": { + "guid": "cb97dd25-d4f7-4185-9e6f-ad6e585c207c" + }, + "organization": { + "guid": "d9be96f5-ea8f-4549-923f-bec882e32e3c" + }, + "links": { + "self": { + "href": "https://api.example.org/v3/audit_events/a595fe2f-01ff-4965-a50c-290258ab8582" + } + } +} diff --git a/tests/v3/test_audit_events.py b/tests/v3/test_audit_events.py new file mode 100644 index 0000000..239812b --- /dev/null +++ b/tests/v3/test_audit_events.py @@ -0,0 +1,39 @@ +import unittest +from http import HTTPStatus + +from abstract_test_case import AbstractTestCase +from cloudfoundry_client.v3.entities import Entity + + +class TestAuditEvents(unittest.TestCase, AbstractTestCase): + @classmethod + def setUpClass(cls): + cls.mock_client_class() + + def setUp(self): + self.build_client() + + def test_list(self): + self.client.get.return_value = self.mock_response( + "/v3/audit_events", + HTTPStatus.OK, + None, + "v3", "audit_events", "GET_response.json" + ) + all_audit_events = [audit_event for audit_event in self.client.v3.audit_events.list()] + self.client.get.assert_called_with(self.client.get.return_value.url) + self.assertEqual(1, len(all_audit_events)) + self.assertEqual(all_audit_events[0]["type"], "audit.app.update") + self.assertIsInstance(all_audit_events[0], Entity) + + def test_get(self): + self.client.get.return_value = self.mock_response( + "/v3/audit_events/audit-event-id", + HTTPStatus.OK, + None, + "v3", "audit_events", "GET_{id}_response.json" + ) + result = self.client.v3.audit_events.get("audit-event-id") + self.client.get.assert_called_with(self.client.get.return_value.url) + self.assertIsNotNone(result) + self.assertIsInstance(result, Entity)