From b383352cfc7697f8384130d638e60cf2cebe31a3 Mon Sep 17 00:00:00 2001 From: ozgen Date: Wed, 6 May 2026 11:56:53 +0200 Subject: [PATCH] add: add get_report_hosts GMP request Implement the get_report_hosts GMP request command. Add unit tests to verify required arguments, filters, pagination handling, and details output. --- gvm/protocols/gmp/_gmpnext.py | 31 +++++++++++ gvm/protocols/gmp/requests/next/__init__.py | 4 ++ .../gmp/requests/next/_report_hosts.py | 46 ++++++++++++++++ .../report_hosts/test_get_report_hosts.py | 55 +++++++++++++++++++ .../gmpnext/entities/test_report_hosts.py | 13 +++++ uv.lock | 2 +- 6 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 gvm/protocols/gmp/requests/next/_report_hosts.py create mode 100644 tests/protocols/gmpnext/entities/report_hosts/test_get_report_hosts.py create mode 100644 tests/protocols/gmpnext/entities/test_report_hosts.py diff --git a/gvm/protocols/gmp/_gmpnext.py b/gvm/protocols/gmp/_gmpnext.py index 8241f718f..a3ebbb789 100644 --- a/gvm/protocols/gmp/_gmpnext.py +++ b/gvm/protocols/gmp/_gmpnext.py @@ -19,6 +19,7 @@ CredentialStores, IntegrationConfigs, OCIImageTargets, + ReportHosts, Tasks, ) from .requests.v224 import HostsOrdering @@ -992,3 +993,33 @@ def modify_integration_config( oidc_provider_client_secret=oidc_provider_client_secret, ) ) + + def get_report_hosts( + self, + report_id: EntityID, + *, + filter_string: str | None = None, + filter_id: str | None = None, + ignore_pagination: bool | None = None, + details: bool | None = True, + ) -> T: + """Request hosts of a single report. + + Args: + report_id: UUID of an existing report. + filter_string: Filter term to use to filter results in the report + filter_id: UUID of filter to use to filter results in the report + ignore_pagination: Whether to ignore the filter terms "first" and + "rows". + details: Request additional report host information details. + Defaults to True. + """ + return self._send_request_and_transform_response( + ReportHosts.get_report_hosts( + report_id=report_id, + filter_string=filter_string, + filter_id=filter_id, + ignore_pagination=ignore_pagination, + details=details, + ) + ) diff --git a/gvm/protocols/gmp/requests/next/__init__.py b/gvm/protocols/gmp/requests/next/__init__.py index 92f47f33d..c9439d411 100644 --- a/gvm/protocols/gmp/requests/next/__init__.py +++ b/gvm/protocols/gmp/requests/next/__init__.py @@ -14,6 +14,9 @@ IntegrationConfigs, ) from gvm.protocols.gmp.requests.next._oci_image_targets import OCIImageTargets +from gvm.protocols.gmp.requests.next._report_hosts import ( + ReportHosts, +) from gvm.protocols.gmp.requests.next._tasks import Tasks from .._entity_id import EntityID @@ -136,6 +139,7 @@ "ReportConfigs", "ReportFormatType", "ReportFormats", + "ReportHosts", "Reports", "ResourceNames", "ResourceType", diff --git a/gvm/protocols/gmp/requests/next/_report_hosts.py b/gvm/protocols/gmp/requests/next/_report_hosts.py new file mode 100644 index 000000000..cb2f0424b --- /dev/null +++ b/gvm/protocols/gmp/requests/next/_report_hosts.py @@ -0,0 +1,46 @@ +from gvm.errors import RequiredArgument +from gvm.protocols.core import Request +from gvm.protocols.gmp.requests import EntityID +from gvm.utils import to_bool +from gvm.xml import XmlCommand + + +class ReportHosts: + @classmethod + def get_report_hosts( + cls, + report_id: EntityID, + *, + filter_string: str | None = None, + filter_id: str | None = None, + ignore_pagination: bool | None = None, + details: bool | None = True, + ) -> Request: + """Request hosts of a single report. + + Args: + report_id: UUID of an existing report. + filter_string: Filter term to use to filter results in the report + filter_id: UUID of filter to use to filter results in the report + ignore_pagination: Whether to ignore the filter terms "first" and + "rows". + details: Request additional report host information details. + Defaults to True. + """ + cmd = XmlCommand("get_report_hosts") + + if not report_id: + raise RequiredArgument( + function=cls.get_report_hosts.__name__, argument="report_id" + ) + + cmd.set_attribute("report_id", str(report_id)) + + cmd.add_filter(filter_string, filter_id) + + if ignore_pagination is not None: + cmd.set_attribute("ignore_pagination", to_bool(ignore_pagination)) + + cmd.set_attribute("details", to_bool(details)) + + return cmd diff --git a/tests/protocols/gmpnext/entities/report_hosts/test_get_report_hosts.py b/tests/protocols/gmpnext/entities/report_hosts/test_get_report_hosts.py new file mode 100644 index 000000000..1d4fc31f6 --- /dev/null +++ b/tests/protocols/gmpnext/entities/report_hosts/test_get_report_hosts.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2026 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from gvm.errors import RequiredArgument + + +class GmpGetReportHostsTestMixin: + def test_get_report_hosts_without_id(self): + with self.assertRaises(RequiredArgument): + self.gmp.get_report_hosts(None) + + with self.assertRaises(RequiredArgument): + self.gmp.get_report_hosts("") + + def test_get_report_hosts_with_filter_string(self): + self.gmp.get_report_hosts(report_id="r1", filter_string="name=foo") + + self.connection.send.has_been_called_with( + b'' + ) + + def test_get_report_hosts_with_filter_id(self): + self.gmp.get_report_hosts(report_id="r1", filter_id="f1") + + self.connection.send.has_been_called_with( + b'' + ) + + def test_get_report_hosts_with_ignore_pagination(self): + self.gmp.get_report_hosts(report_id="r1", ignore_pagination=True) + + self.connection.send.has_been_called_with( + b'' + ) + + self.gmp.get_report_hosts(report_id="r1", ignore_pagination=False) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_get_report_hosts_with_details(self): + self.gmp.get_report_hosts(report_id="r1", details=True) + + self.connection.send.has_been_called_with( + b'' + ) + + self.gmp.get_report_hosts(report_id="r1", details=False) + + self.connection.send.has_been_called_with( + b'' + ) diff --git a/tests/protocols/gmpnext/entities/test_report_hosts.py b/tests/protocols/gmpnext/entities/test_report_hosts.py new file mode 100644 index 000000000..d82f40e6d --- /dev/null +++ b/tests/protocols/gmpnext/entities/test_report_hosts.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2026 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from ...gmpnext import GMPTestCase +from .report_hosts.test_get_report_hosts import ( + GmpGetReportHostsTestMixin, +) + + +class GmpGetReportHostsTestCase(GmpGetReportHostsTestMixin, GMPTestCase): + pass diff --git a/uv.lock b/uv.lock index cff749695..c8c2ee9e9 100644 --- a/uv.lock +++ b/uv.lock @@ -1267,7 +1267,7 @@ wheels = [ [[package]] name = "python-gvm" -version = "27.0.2.dev1" +version = "27.0.3.dev1" source = { editable = "." } dependencies = [ { name = "httpx", extra = ["http2"] },