Skip to content

Commit 21b6fa7

Browse files
committed
Merge branch 'development' into alex_nvme
2 parents 92aaa01 + 5516a9e commit 21b6fa7

File tree

12 files changed

+168
-32
lines changed

12 files changed

+168
-32
lines changed

nodescraper/cli/helper.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,13 @@ def generate_reference_config(
344344

345345
plugin = plugin_reg.plugins.get(obj.source)
346346

347-
args = extract_analyzer_args_from_model(plugin, data_model, logger)
348-
if not args:
349-
continue
350-
plugins[obj.source] = {"analysis_args": {}}
351-
plugins[obj.source]["analysis_args"] = args.model_dump(exclude_none=True)
347+
if obj.source not in plugins:
348+
plugins[obj.source] = {}
349+
350+
a_args = extract_analyzer_args_from_model(plugin, data_model, logger)
351+
if a_args:
352+
plugins[obj.source]["analysis_args"] = a_args.model_dump(exclude_none=True)
353+
352354
plugin_config.plugins = plugins
353355

354356
return plugin_config

nodescraper/interfaces/dataplugin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ def analyze(
241241
Returns:
242242
TaskResult: result of data analysis
243243
"""
244+
244245
if self.ANALYZER is None:
245246
self.analysis_result = TaskResult(
246247
status=ExecutionStatus.NOT_RAN,

nodescraper/interfaces/task.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def max_event_priority_level(self) -> EventPriority:
8080
def max_event_priority_level(self, input_value: str | EventPriority):
8181
if isinstance(input_value, str):
8282
value: EventPriority = getattr(EventPriority, input_value)
83+
elif isinstance(input_value, int):
84+
value = EventPriority(input_value)
8385
elif isinstance(input_value, EventPriority):
8486
value: EventPriority = input_value
8587
else:

nodescraper/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#
2525
###############################################################################
2626
from .analyzerargs import AnalyzerArgs
27+
from .collectorargs import CollectorArgs
2728
from .datamodel import DataModel
2829
from .datapluginresult import DataPluginResult
2930
from .event import Event
@@ -35,6 +36,7 @@
3536

3637
__all__ = [
3738
"AnalyzerArgs",
39+
"CollectorArgs",
3840
"DataModel",
3941
"TaskResult",
4042
"Event",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
###############################################################################
2+
#
3+
# MIT License
4+
#
5+
# Copyright (c) 2025 Advanced Micro Devices, Inc.
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in all
15+
# copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
# SOFTWARE.
24+
#
25+
###############################################################################
26+
from pydantic import BaseModel
27+
28+
29+
class CollectorArgs(BaseModel):
30+
model_config = {"extra": "forbid", "exclude_none": True}

nodescraper/pluginexecutor.py

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from pydantic import BaseModel
3434

3535
from nodescraper.constants import DEFAULT_LOGGER
36-
from nodescraper.interfaces import ConnectionManager, DataPlugin
36+
from nodescraper.interfaces import ConnectionManager, DataPlugin, PluginInterface
3737
from nodescraper.models import PluginConfig, SystemInfo
3838
from nodescraper.models.pluginresult import PluginResult
3939
from nodescraper.pluginregistry import PluginRegistry
@@ -165,16 +165,25 @@ def run_queue(self) -> list[PluginResult]:
165165
plugin_inst = plugin_class(**init_payload)
166166

167167
run_payload = copy.deepcopy(plugin_args)
168-
169168
run_args = TypeUtils.get_func_arg_types(plugin_class.run, plugin_class)
169+
170170
for arg in run_args.keys():
171171
if arg == "preserve_connection" and issubclass(plugin_class, DataPlugin):
172172
run_payload[arg] = True
173-
elif arg in self.plugin_config.global_args:
174-
run_payload[arg] = self.plugin_config.global_args[arg]
175173

176-
# TODO
177-
# enable global substitution in collection and analysis args
174+
try:
175+
global_run_args = self.apply_global_args_to_plugin(
176+
plugin_inst, plugin_class, self.plugin_config.global_args
177+
)
178+
run_payload.update(global_run_args)
179+
except ValueError as ve:
180+
self.logger.error(
181+
"Invalid global_args for plugin %s: %s. Skipping plugin.",
182+
plugin_name,
183+
str(ve),
184+
)
185+
continue
186+
178187
self.logger.info("-" * 50)
179188
plugin_results.append(plugin_inst.run(**run_payload))
180189
except Exception as e:
@@ -210,3 +219,42 @@ def run_queue(self) -> list[PluginResult]:
210219
)
211220

212221
return plugin_results
222+
223+
def apply_global_args_to_plugin(
224+
self,
225+
plugin_inst: PluginInterface,
226+
plugin_class: type,
227+
global_args: dict,
228+
) -> dict:
229+
"""
230+
Applies global arguments to the plugin instance, including standard attributes
231+
and merging Pydantic model arguments (collection_args, analysis_args).
232+
233+
Args:
234+
plugin_inst: The plugin instance to update.
235+
plugin_class: The plugin class (needed for model instantiation).
236+
global_args: Dict of global argument overrides.
237+
"""
238+
239+
run_args = {}
240+
for key in global_args:
241+
if key in ["collection_args", "analysis_args"] and isinstance(plugin_inst, DataPlugin):
242+
continue
243+
else:
244+
run_args[key] = global_args[key]
245+
246+
if "collection_args" in global_args and hasattr(plugin_class, "COLLECTOR_ARGS"):
247+
plugin_fields = set(plugin_class.COLLECTOR_ARGS.__fields__.keys())
248+
filtered = {
249+
k: v for k, v in global_args["collection_args"].items() if k in plugin_fields
250+
}
251+
if filtered:
252+
run_args["collection_args"] = filtered
253+
254+
if "analysis_args" in global_args and hasattr(plugin_class, "ANALYZER_ARGS"):
255+
plugin_fields = set(plugin_class.ANALYZER_ARGS.__fields__.keys())
256+
filtered = {k: v for k, v in global_args["analysis_args"].items() if k in plugin_fields}
257+
if filtered:
258+
run_args["analysis_args"] = filtered
259+
260+
return run_args

nodescraper/plugins/inband/process/collector_args.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@
2323
# SOFTWARE.
2424
#
2525
###############################################################################
26-
from pydantic import BaseModel
2726

27+
from nodescraper.models import CollectorArgs
2828

29-
class ProcessCollectorArgs(BaseModel):
30-
top_n_process: int = 10
3129

32-
model_config = {"extra": "forbid"}
30+
class ProcessCollectorArgs(CollectorArgs):
31+
top_n_process: int = 10

nodescraper/plugins/inband/process/process_plugin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ class ProcessPlugin(InBandDataPlugin[ProcessDataModel, ProcessCollectorArgs, Pro
4242
ANALYZER = ProcessAnalyzer
4343

4444
ANALYZER_ARGS = ProcessAnalyzerArgs
45+
46+
COLLECTOR_ARGS = ProcessCollectorArgs

test/unit/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class DummyDataModel(DataModel):
5555

5656
class DummyArg(BaseModel):
5757
value: int
58+
regex_match: bool = True
5859

5960

6061
class DummyResult:

test/unit/framework/common/shared_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ class TestModelArg(AnalyzerArgs):
7272

7373
@classmethod
7474
def build_from_model(cls, model):
75-
return cls(model_attr=int(model.some_version))
75+
return cls(model_attr=int(model.foo))
7676

7777

7878
class DummyDataModel(DataModel):
79-
some_version: str = None
79+
foo: str = None
8080

8181

8282
class TestPluginA(PluginInterface[MockConnectionManager, None]):

0 commit comments

Comments
 (0)