77from gvm .errors import RequiredArgument
88from gvm .protocols .core import Request
99from gvm .protocols .gmp .requests ._entity_id import EntityID
10- from gvm .utils import to_bool
10+ from gvm .utils import SupportsStr , to_bool
1111from gvm .xml import XmlCommand
1212
1313
1414class Agents :
1515
1616 @staticmethod
17- def _add_el ( parent , name : str , value ) -> None :
17+ def _add_element ( element , name : str , value : Optional [ SupportsStr ] ) -> None :
1818 """
1919 Helper to add a sub-element with a value if the value is not None.
2020
2121 Args:
22- parent : The XML parent element to which the new element is added.
22+ element : The XML parent element to which the new element is added.
2323 name: Name of the sub-element to create.
2424 value: Value to set as the text of the sub-element. If None, the
2525 element will not be created.
2626 """
2727 if value is not None :
28- parent .add_element (name , str (value ))
28+ element .add_element (name , str (value ))
29+
30+ @classmethod
31+ def _validate_agent_config (
32+ cls , config : Mapping [str , Any ], * , caller : str
33+ ) -> None :
34+ """Ensure all required fields exist and are non-empty."""
35+
36+ def valid (d : Mapping [str , Any ], key : str , path : str ):
37+ if (
38+ not isinstance (d , Mapping )
39+ or d .get (key ) is None
40+ or d .get (key ) == ""
41+ ):
42+ raise RequiredArgument (
43+ function = caller , argument = f"config.{ path } { key } "
44+ )
45+
46+ # agent_control.retry
47+ ac = config .get ("agent_control" )
48+ valid (config , "agent_control" , "" )
49+ retry = ac .get ("retry" ) if isinstance (ac , Mapping ) else None
50+ valid (ac , "retry" , "agent_control." )
51+ valid (retry , "attempts" , "agent_control.retry." )
52+ valid (retry , "delay_in_seconds" , "agent_control.retry." )
53+ valid (retry , "max_jitter_in_seconds" , "agent_control.retry." )
54+
55+ # agent_script_executor
56+ se = config .get ("agent_script_executor" )
57+ valid (config , "agent_script_executor" , "" )
58+ valid (se , "bulk_size" , "agent_script_executor." )
59+ valid (se , "bulk_throttle_time_in_ms" , "agent_script_executor." )
60+ valid (se , "indexer_dir_depth" , "agent_script_executor." )
61+
62+ sched = (
63+ se .get ("scheduler_cron_time" ) if isinstance (se , Mapping ) else None
64+ )
65+ if isinstance (sched , (list , tuple , set )):
66+ items = list (sched )
67+ else :
68+ items = []
69+ if not items or any (str (x ).strip () == "" for x in items ):
70+ raise RequiredArgument (
71+ function = caller ,
72+ argument = "config.agent_script_executor.scheduler_cron_time" ,
73+ )
74+
75+ # heartbeat
76+ hb = config .get ("heartbeat" )
77+ valid (config , "heartbeat" , "" )
78+ valid (hb , "interval_in_seconds" , "heartbeat." )
79+ valid (hb , "miss_until_inactive" , "heartbeat." )
2980
3081 @classmethod
3182 def _append_agent_config (cls , parent , config : Mapping [str , Any ]) -> None :
@@ -67,11 +118,11 @@ def _append_agent_config(cls, parent, config: Mapping[str, Any]) -> None:
67118 retry = ac ["retry" ]
68119 xml_ac = xml_config .add_element ("agent_control" )
69120 xml_retry = xml_ac .add_element ("retry" )
70- cls ._add_el (xml_retry , "attempts" , retry .get ("attempts" ))
71- cls ._add_el (
121+ cls ._add_element (xml_retry , "attempts" , retry .get ("attempts" ))
122+ cls ._add_element (
72123 xml_retry , "delay_in_seconds" , retry .get ("delay_in_seconds" )
73124 )
74- cls ._add_el (
125+ cls ._add_element (
75126 xml_retry ,
76127 "max_jitter_in_seconds" ,
77128 retry .get ("max_jitter_in_seconds" ),
@@ -80,26 +131,27 @@ def _append_agent_config(cls, parent, config: Mapping[str, Any]) -> None:
80131 # agent_script_executor
81132 se = config ["agent_script_executor" ]
82133 xml_se = xml_config .add_element ("agent_script_executor" )
83- cls ._add_el (xml_se , "bulk_size" , se .get ("bulk_size" ))
84- cls ._add_el (
134+ cls ._add_element (xml_se , "bulk_size" , se .get ("bulk_size" ))
135+ cls ._add_element (
85136 xml_se ,
86137 "bulk_throttle_time_in_ms" ,
87138 se .get ("bulk_throttle_time_in_ms" ),
88139 )
89- cls ._add_el (xml_se , "indexer_dir_depth" , se .get ("indexer_dir_depth" ))
140+ cls ._add_element (
141+ xml_se , "indexer_dir_depth" , se .get ("indexer_dir_depth" )
142+ )
90143 sched = se .get ("scheduler_cron_time" )
91- if sched :
92- xml_sched = xml_se .add_element ("scheduler_cron_time" )
93- for item in sched :
94- xml_sched .add_element ("item" , str (item ))
144+ xml_sched = xml_se .add_element ("scheduler_cron_time" )
145+ for item in sched :
146+ xml_sched .add_element ("item" , str (item ))
95147
96148 # heartbeat
97149 hb = config ["heartbeat" ]
98150 xml_hb = xml_config .add_element ("heartbeat" )
99- cls ._add_el (
151+ cls ._add_element (
100152 xml_hb , "interval_in_seconds" , hb .get ("interval_in_seconds" )
101153 )
102- cls ._add_el (
154+ cls ._add_element (
103155 xml_hb , "miss_until_inactive" , hb .get ("miss_until_inactive" )
104156 )
105157
@@ -178,6 +230,9 @@ def modify_agents(
178230 cmd .add_element ("authorized" , to_bool (authorized ))
179231
180232 if config is not None :
233+ cls ._validate_agent_config (
234+ config , caller = cls .modify_agents .__name__
235+ )
181236 cls ._append_agent_config (cmd , config )
182237
183238 if comment :
@@ -248,6 +303,10 @@ def modify_agent_control_scan_config(
248303 argument = "config" ,
249304 )
250305
306+ cls ._validate_agent_config (
307+ config , caller = cls .modify_agent_control_scan_config .__name__
308+ )
309+
251310 cmd = XmlCommand (
252311 "modify_agent_control_scan_config" ,
253312 )
0 commit comments