Skip to content

Commit 4a1c6ca

Browse files
committed
kernelci: api: helper: recurse through ancestors for evaluating rules
We used to check rules against the node being created and its direct parent. With the addition of post-processing nodes for test jobs, this is no longer sufficient as job `nodes` are lacking some of the fields contained in `kbuild` nodes. Fix this by looking recursively at all ancestors. Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
1 parent ee64d7e commit 4a1c6ca

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

kernelci/api/helper.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ def receive_event_node(self, sub_id):
134134

135135
def _find_container(self, field, node):
136136
"""
137-
Return the first found dict containing a field of a given name
137+
Return the first found dict containing a field of a given name,
138+
recursing through all of the node's ancestors if not found.
138139
"""
139140
for item in node:
140141
if isinstance(node[item], dict):
@@ -143,24 +144,24 @@ def _find_container(self, field, node):
143144
return base_object
144145
elif field == item:
145146
return node
147+
if 'parent' in node:
148+
parent = self._api.node.get(node['parent'])
149+
return self._find_container(field, parent)
146150
return None
147151

148-
# pylint: disable=too-many-arguments
149-
def _is_allowed(self, rules, key, node, parent):
152+
def _is_allowed(self, rules, key, node):
150153
"""
151154
Check whether the value of a specific node attribute matches
152155
a filtering rule. As the specified attribute might not be present
153156
in the node being created, we fall back to checking the value in its
154-
parent node in such cases.
157+
ancestor nodes.
155158
156159
Returns True if the rule allows the current value, False otherwise.
157160
"""
158161

159-
# Find the node (or parent node) attribute corresponding to the
162+
# Find the node (or ancestor node) attribute corresponding to the
160163
# rule we're applying
161164
base = self._find_container(key, node)
162-
if not base and parent:
163-
base = self._find_container(key, parent)
164165
if not base:
165166
return True
166167

@@ -294,7 +295,7 @@ def _is_tree_branch_allowed(self, node, rules):
294295

295296
return True
296297

297-
def should_create_node(self, rules, node, parent=None):
298+
def should_create_node(self, rules, node):
298299
"""
299300
Check whether a node should be created based on configured rules.
300301
Those can be specified in the job, platform or runtime configuration
@@ -356,11 +357,9 @@ def should_create_node(self, rules, node, parent=None):
356357
# Process the tree and branch rules first as they need specific processing
357358
# for handling tree/branch combinations
358359

359-
# Find the node (or parent node) attribute containing the "tree" (and therefore
360+
# Find the node (or ancestor node) attribute containing the "tree" (and therefore
360361
# "branch") value
361362
ref_base = self._find_container("tree", node)
362-
if not ref_base and parent:
363-
ref_base = self._find_container("tree", parent)
364363
if ref_base and not self._is_tree_branch_allowed(ref_base, rules):
365364
return False
366365

@@ -390,7 +389,7 @@ def should_create_node(self, rules, node, parent=None):
390389
f"({rule_major}.{rule_minor})")
391390
return False
392391

393-
elif not self._is_allowed(rules, key, node, parent):
392+
elif not self._is_allowed(rules, key, node):
394393
return False
395394

396395
return True
@@ -440,6 +439,7 @@ def _is_job_filtered(self, node):
440439

441440
return False
442441

442+
# pylint: disable=too-many-arguments
443443
def create_job_node(self, job_config, input_node,
444444
runtime=None, platform=None, retry_counter=0):
445445
"""Create a new job node based on input and configuration"""
@@ -471,7 +471,7 @@ def create_job_node(self, job_config, input_node,
471471
f"for node {input_node['id']}")
472472
return None
473473

474-
if not self.should_create_node(job_config.rules, job_node, input_node):
474+
if not self.should_create_node(job_config.rules, job_node):
475475
print(f"Not creating node due to job rules for {job_config.name} "
476476
f"evaluating node {input_node['id']}")
477477
return None
@@ -489,7 +489,7 @@ def create_job_node(self, job_config, input_node,
489489
# in case of kubernetes: cluster name
490490
if runtime:
491491
job_node['data']['runtime'] = runtime.config.name
492-
if not self.should_create_node(runtime.config.rules, job_node, input_node):
492+
if not self.should_create_node(runtime.config.rules, job_node):
493493
print(f"Not creating node {input_node['id']} due to runtime rules "
494494
f"for {runtime.config.name}")
495495
return None
@@ -502,7 +502,7 @@ def create_job_node(self, job_config, input_node,
502502
f"for node {input_node['id']}")
503503
return None
504504
job_node['data']['platform'] = platform.name
505-
if not self.should_create_node(platform.rules, job_node, input_node):
505+
if not self.should_create_node(platform.rules, job_node):
506506
print(f"Not creating node {input_node['id']} due to platform rules "
507507
f"for {platform.name}")
508508
return None

0 commit comments

Comments
 (0)