Skip to content

Commit 73e8626

Browse files
a-h-abdelsalamgreenbonebot
authored andcommitted
Add: Added GMP commands for OCI image targets
1 parent 4be8ae6 commit 73e8626

11 files changed

+649
-1
lines changed

gvm/protocols/gmp/_gmpnext.py

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from .._protocol import T
1010
from ._gmp227 import GMPv227
11-
from .requests.next import AgentGroups, AgentInstallers, Agents
11+
from .requests.next import AgentGroups, AgentInstallers, Agents, OCIImageTargets
1212

1313

1414
class GMPNext(GMPv227[T]):
@@ -274,3 +274,121 @@ def clone_agent_group(
274274
return self._send_request_and_transform_response(
275275
AgentGroups.clone_agent_group(agent_group_id)
276276
)
277+
278+
def create_oci_image_target(
279+
self,
280+
name: str,
281+
image_references: list[str],
282+
*,
283+
comment: Optional[str] = None,
284+
credential_id: Optional[EntityID] = None,
285+
) -> T:
286+
"""Create a new OCI image target
287+
288+
Args:
289+
name: Name of the OCI image target
290+
image_references: List of OCI image URLs to scan
291+
comment: Comment for the target
292+
credential_id: UUID of a credential to use on target
293+
"""
294+
return self._send_request_and_transform_response(
295+
OCIImageTargets.create_oci_image_target(
296+
name=name,
297+
image_references=image_references,
298+
comment=comment,
299+
credential_id=credential_id,
300+
)
301+
)
302+
303+
def modify_oci_image_target(
304+
self,
305+
oci_image_target_id: EntityID,
306+
*,
307+
name: Optional[str] = None,
308+
comment: Optional[str] = None,
309+
image_references: Optional[list[str]] = None,
310+
credential_id: Optional[EntityID] = None,
311+
) -> T:
312+
"""Modify an existing OCI image target.
313+
314+
Args:
315+
oci_image_target_id: UUID of target to modify.
316+
comment: Comment on target.
317+
name: Name of target.
318+
image_references: List of OCI image URLs to scan.
319+
credential_id: UUID of credential to use on target.
320+
"""
321+
return self._send_request_and_transform_response(
322+
OCIImageTargets.modify_oci_image_target(
323+
oci_image_target_id,
324+
name=name,
325+
comment=comment,
326+
image_references=image_references,
327+
credential_id=credential_id,
328+
)
329+
)
330+
331+
def clone_oci_image_target(self, oci_image_target_id: EntityID) -> T:
332+
"""Clone an existing OCI image target.
333+
334+
Args:
335+
oci_image_target_id: UUID of an existing OCI image target to clone.
336+
"""
337+
return self._send_request_and_transform_response(
338+
OCIImageTargets.clone_oci_image_target(oci_image_target_id)
339+
)
340+
341+
def delete_oci_image_target(
342+
self, oci_image_target_id: EntityID, *, ultimate: Optional[bool] = False
343+
) -> T:
344+
"""Delete an existing OCI image target.
345+
346+
Args:
347+
oci_image_target_id: UUID of an existing OCI image target to delete.
348+
ultimate: Whether to remove entirely or to the trashcan.
349+
"""
350+
return self._send_request_and_transform_response(
351+
OCIImageTargets.delete_oci_image_target(
352+
oci_image_target_id, ultimate=ultimate
353+
)
354+
)
355+
356+
def get_oci_image_target(
357+
self, oci_image_target_id: EntityID, *, tasks: Optional[bool] = None
358+
) -> T:
359+
"""Request a single OCI image target.
360+
361+
Args:
362+
oci_image_target_id: UUID of the OCI image target to request.
363+
tasks: Whether to include list of tasks that use the target
364+
"""
365+
return self._send_request_and_transform_response(
366+
OCIImageTargets.get_oci_image_target(
367+
oci_image_target_id, tasks=tasks
368+
)
369+
)
370+
371+
def get_oci_image_targets(
372+
self,
373+
*,
374+
filter_string: Optional[str] = None,
375+
filter_id: Optional[EntityID] = None,
376+
trash: Optional[bool] = None,
377+
tasks: Optional[bool] = None,
378+
) -> T:
379+
"""Request a list of OCI image targets.
380+
381+
Args:
382+
filter_string: Filter term to use for the query.
383+
filter_id: UUID of an existing filter to use for the query.
384+
trash: Whether to include targets in the trashcan.
385+
tasks: Whether to include list of tasks that use the target.
386+
"""
387+
return self._send_request_and_transform_response(
388+
OCIImageTargets.get_oci_image_targets(
389+
filter_string=filter_string,
390+
filter_id=filter_id,
391+
trash=trash,
392+
tasks=tasks,
393+
)
394+
)

gvm/protocols/gmp/requests/next/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from gvm.protocols.gmp.requests.next._agent_groups import AgentGroups
66
from gvm.protocols.gmp.requests.next._agent_installers import AgentInstallers
77
from gvm.protocols.gmp.requests.next._agents import Agents
8+
from gvm.protocols.gmp.requests.next._oci_image_targets import OCIImageTargets
89

910
from .._entity_id import EntityID
1011
from .._version import Version
@@ -113,6 +114,7 @@
113114
"InfoType",
114115
"Notes",
115116
"Nvts",
117+
"OCIImageTargets",
116118
"OperatingSystems",
117119
"Overrides",
118120
"Permissions",
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# SPDX-FileCopyrightText: 2025 Greenbone AG
2+
#
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
#
5+
6+
from typing import Optional
7+
8+
from gvm.errors import RequiredArgument
9+
from gvm.protocols.core import Request
10+
from gvm.protocols.gmp.requests._entity_id import EntityID
11+
from gvm.utils import to_bool, to_comma_list
12+
from gvm.xml import XmlCommand
13+
14+
15+
class OCIImageTargets:
16+
@classmethod
17+
def create_oci_image_target(
18+
cls,
19+
name: str,
20+
image_references: list[str],
21+
*,
22+
comment: Optional[str] = None,
23+
credential_id: Optional[EntityID] = None,
24+
) -> Request:
25+
"""Create a new OCI image target
26+
27+
Args:
28+
name: Name of the target
29+
image_references: List of OCI image URLs to scan
30+
comment: Comment for the target
31+
credential_id: UUID of a credential to use on target
32+
"""
33+
if not name:
34+
raise RequiredArgument(
35+
function=cls.create_oci_image_target.__name__, argument="name"
36+
)
37+
38+
if not image_references:
39+
raise RequiredArgument(
40+
function=cls.create_oci_image_target.__name__,
41+
argument="image_references",
42+
)
43+
44+
cmd = XmlCommand("create_oci_image_target")
45+
cmd.add_element("name", name)
46+
cmd.add_element("image_references", to_comma_list(image_references))
47+
48+
if comment:
49+
cmd.add_element("comment", comment)
50+
51+
if credential_id:
52+
cmd.add_element("credential", attrs={"id": str(credential_id)})
53+
54+
return cmd
55+
56+
@classmethod
57+
def modify_oci_image_target(
58+
cls,
59+
oci_image_target_id: EntityID,
60+
*,
61+
name: Optional[str] = None,
62+
comment: Optional[str] = None,
63+
image_references: Optional[list[str]] = None,
64+
credential_id: Optional[EntityID] = None,
65+
) -> Request:
66+
"""Modify an existing target.
67+
68+
Args:
69+
oci_image_target_id: UUID of target to modify.
70+
comment: Comment on target.
71+
name: Name of target.
72+
image_references: List of OCI image URLs.
73+
credential_id: UUID of credential to use on target.
74+
"""
75+
if not oci_image_target_id:
76+
raise RequiredArgument(
77+
function=cls.modify_oci_image_target.__name__,
78+
argument="oci_image_target_id",
79+
)
80+
81+
cmd = XmlCommand("modify_oci_image_target")
82+
cmd.set_attribute("oci_image_target_id", str(oci_image_target_id))
83+
84+
if comment:
85+
cmd.add_element("comment", comment)
86+
87+
if name:
88+
cmd.add_element("name", name)
89+
90+
if image_references:
91+
cmd.add_element("image_references", to_comma_list(image_references))
92+
93+
if credential_id:
94+
cmd.add_element("credential", attrs={"id": str(credential_id)})
95+
96+
return cmd
97+
98+
@classmethod
99+
def clone_oci_image_target(cls, oci_image_target_id: EntityID) -> Request:
100+
"""Clone an existing OCI image target.
101+
102+
Args:
103+
oci_image_target_id: UUID of an existing target to clone.
104+
"""
105+
if not oci_image_target_id:
106+
raise RequiredArgument(
107+
function=cls.clone_oci_image_target.__name__,
108+
argument="oci_image_target_id",
109+
)
110+
111+
cmd = XmlCommand("create_oci_image_target")
112+
cmd.add_element("copy", str(oci_image_target_id))
113+
return cmd
114+
115+
@classmethod
116+
def delete_oci_image_target(
117+
cls, oci_image_target_id: EntityID, *, ultimate: Optional[bool] = False
118+
) -> Request:
119+
"""Delete an existing OCI image target.
120+
121+
Args:
122+
oci_image_target_id: UUID of an existing target to delete.
123+
ultimate: Whether to remove entirely or to the trashcan.
124+
"""
125+
if not oci_image_target_id:
126+
raise RequiredArgument(
127+
function=cls.delete_oci_image_target.__name__,
128+
argument="oci_image_target_id",
129+
)
130+
131+
cmd = XmlCommand("delete_oci_image_target")
132+
cmd.set_attribute("oci_image_target_id", str(oci_image_target_id))
133+
cmd.set_attribute("ultimate", to_bool(ultimate))
134+
return cmd
135+
136+
@classmethod
137+
def get_oci_image_target(
138+
cls, oci_image_target_id: EntityID, *, tasks: Optional[bool] = None
139+
) -> Request:
140+
"""Request a single OCI Image target.
141+
142+
Args:
143+
oci_image_target_id: UUID of the target to request.
144+
tasks: Whether to include list of tasks that use the target
145+
"""
146+
if not oci_image_target_id:
147+
raise RequiredArgument(
148+
function=cls.get_oci_image_target.__name__,
149+
argument="oci_image_target_id",
150+
)
151+
152+
cmd = XmlCommand("get_oci_image_targets")
153+
cmd.set_attribute("oci_image_target_id", str(oci_image_target_id))
154+
155+
if tasks is not None:
156+
cmd.set_attribute("tasks", to_bool(tasks))
157+
158+
return cmd
159+
160+
@classmethod
161+
def get_oci_image_targets(
162+
cls,
163+
*,
164+
filter_string: Optional[str] = None,
165+
filter_id: Optional[EntityID] = None,
166+
trash: Optional[bool] = None,
167+
tasks: Optional[bool] = None,
168+
) -> Request:
169+
"""Request a list of OCI image targets.
170+
171+
Args:
172+
filter_string: Filter term to use for the query.
173+
filter_id: UUID of an existing filter to use for the query.
174+
trash: Whether to include targets in the trashcan.
175+
tasks: Whether to include list of tasks that use the target.
176+
"""
177+
cmd = XmlCommand("get_oci_image_targets")
178+
cmd.add_filter(filter_string, filter_id)
179+
180+
if trash is not None:
181+
cmd.set_attribute("trash", to_bool(trash))
182+
183+
if tasks is not None:
184+
cmd.set_attribute("tasks", to_bool(tasks))
185+
186+
return cmd
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# SPDX-FileCopyrightText: 2025 Greenbone AG
2+
#
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
#
5+
6+
from .test_clone_oci_image_target import GmpCloneOCIImageTargetTestMixin
7+
from .test_create_oci_image_target import GmpCreateOCIImageTargetTestMixin
8+
from .test_delete_oci_image_target import GmpDeleteOCIImageTargetTestMixin
9+
from .test_get_oci_image_target import GmpGetOCIImageTargetTestMixin
10+
from .test_get_oci_image_targets import GmpGetOCIImageTargetsTestMixin
11+
from .test_modify_oci_image_target import GmpModifyOCIImageTargetTestMixin
12+
13+
__all__ = (
14+
"GmpCloneOCIImageTargetTestMixin",
15+
"GmpCreateOCIImageTargetTestMixin",
16+
"GmpDeleteOCIImageTargetTestMixin",
17+
"GmpGetOCIImageTargetTestMixin",
18+
"GmpGetOCIImageTargetsTestMixin",
19+
"GmpModifyOCIImageTargetTestMixin",
20+
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# SPDX-FileCopyrightText: 2025 Greenbone AG
2+
#
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
#
5+
6+
from gvm.errors import RequiredArgument
7+
8+
9+
class GmpCloneOCIImageTargetTestMixin:
10+
TARGET_ID = "00000000-0000-0000-0000-000000000000"
11+
12+
def test_clone(self):
13+
self.gmp.clone_oci_image_target(self.TARGET_ID)
14+
15+
self.connection.send.has_been_called_with(
16+
"<create_oci_image_target>"
17+
f"<copy>{self.TARGET_ID}</copy>"
18+
"</create_oci_image_target>".encode("utf-8")
19+
)
20+
21+
def test_missing_id(self):
22+
with self.assertRaises(RequiredArgument):
23+
self.gmp.clone_oci_image_target("")
24+
25+
with self.assertRaises(RequiredArgument):
26+
self.gmp.clone_oci_image_target(None)

0 commit comments

Comments
 (0)