Skip to content

Commit c3b4a9b

Browse files
elsaferraraleocardao
authored andcommitted
Add CheckVirus action
Virus check should be done in a separated event so that upload event result won't be affected by the virus check result. ref: eng/shared/release#1578
1 parent 44257cf commit c3b4a9b

File tree

4 files changed

+68
-17
lines changed

4 files changed

+68
-17
lines changed

src/e3/anod/action/__init__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,29 @@ def __str__(self) -> str:
359359
return f"upload source {self.source_name}"
360360

361361

362+
class CheckVirus(Action):
363+
"""CheckVirus Action.
364+
365+
Check virus on uploaded component.
366+
"""
367+
368+
__slots__ = ("uid", "data", "anod_instance")
369+
370+
def __init__(self, data: Anod):
371+
"""Initialize a CheckVirus object.
372+
373+
:param data: Anod instance
374+
"""
375+
data_uid = data.uid.split(".")
376+
data_uid[-1] = "check_virus"
377+
uid = ".".join(data_uid)
378+
super().__init__(uid=uid, data=data)
379+
self.anod_instance = data
380+
381+
def __str__(self) -> str:
382+
return f"check for viruses in {self.uid.rsplit('.', 1)[0]}"
383+
384+
362385
class Decision(Action, metaclass=abc.ABCMeta):
363386
"""Decision Action.
364387

src/e3/anod/context.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
UploadBinaryComponent,
2323
UploadSource,
2424
UploadSourceComponent,
25+
CheckVirus,
2526
)
2627
from e3.anod.deps import Dependency
2728
from e3.anod.error import AnodError
@@ -398,8 +399,10 @@ def add_anod_action(
398399
spec = build_action.data
399400
if spec.component is not None and upload:
400401
upload_bin: UploadBinaryComponent | UploadSourceComponent
402+
check_virus: None | CheckVirus = None
401403
if spec.has_package:
402404
upload_bin = UploadBinaryComponent(spec)
405+
check_virus = CheckVirus(spec)
403406
else:
404407
upload_bin = UploadSourceComponent(spec)
405408
self.add(upload_bin)
@@ -410,7 +413,12 @@ def add_anod_action(
410413
plan_line=plan_line,
411414
plan_args=plan_args,
412415
)
413-
self.connect(self.root, upload_bin)
416+
if check_virus:
417+
self.add(check_virus)
418+
self.connect(self.root, check_virus)
419+
self.connect(check_virus, upload_bin)
420+
else:
421+
self.connect(self.root, upload_bin)
414422
self.connect(upload_bin, build_action)
415423

416424
elif primitive == "install":
@@ -961,7 +969,7 @@ def schedule(self, resolver: ResolverType) -> DAG:
961969
for which a decision should be taken
962970
"""
963971
rev = self.tree.reverse_graph(enable_checks=False)
964-
uploads: list[tuple[Upload, frozenset[VertexID]]] = []
972+
uploads: list[tuple[Upload | CheckVirus, frozenset[VertexID], bool]] = []
965973
dag = DAG()
966974

967975
# Retrieve existing tags
@@ -981,8 +989,14 @@ def schedule(self, resolver: ResolverType) -> DAG:
981989
# to apply the triggers based on the current list of scheduled
982990
# actions.
983991
action.apply_triggers(dag)
984-
elif isinstance(action, Upload):
985-
uploads.append((action, self.tree.get_predecessors(uid)))
992+
elif isinstance(action, (Upload, CheckVirus)):
993+
uploads.append(
994+
(
995+
action,
996+
self.tree.get_predecessors(uid),
997+
"root" in self.tree.get_successors(uid),
998+
)
999+
)
9861000
else:
9871001
if TYPE_CHECKING:
9881002
assert isinstance(action, Action)
@@ -1057,15 +1071,24 @@ def schedule(self, resolver: ResolverType) -> DAG:
10571071
a, predecessors=[uid], enable_checks=False
10581072
)
10591073

1060-
# Handle Upload nodes. Add the node only if all predecessors
1061-
# are scheduled.
1062-
for action, predecessors in uploads:
1063-
if len([p for p in predecessors if p not in dag]) == 0:
1074+
# Handle uploads related nodes.
1075+
# Upload nodes were added to the uploads list from a reverse DAG, we
1076+
# have to reverse the list to have the correct sequence.
1077+
uploads.reverse()
1078+
for upload_action, predecessors, connect_to_root in uploads:
1079+
# Add the node only if all predecessors are scheduled.
1080+
p_not_in_dag = [p for p in predecessors if p not in dag]
1081+
if len(p_not_in_dag) == 0:
10641082
dag.update_vertex(
1065-
action.uid, action, predecessors=predecessors, enable_checks=False
1066-
)
1067-
# connect upload to the root node
1068-
dag.update_vertex(
1069-
"root", predecessors=[action.uid], enable_checks=False
1083+
upload_action.uid,
1084+
upload_action,
1085+
predecessors=predecessors,
1086+
enable_checks=False,
10701087
)
1088+
# Last action of the uploads should be connected to the dag's root.
1089+
if connect_to_root:
1090+
dag.update_vertex(
1091+
"root", predecessors=[upload_action.uid], enable_checks=False
1092+
)
1093+
10711094
return dag

tests/tests_e3/anod/action/main_test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class Spec(e3.anod.spec.Anod):
8383
upload_source = action.UploadSourceComponent(data=build_spec)
8484
assert str(upload_source).startswith("upload source metadata of ")
8585

86+
check_virus = action.CheckVirus(data=build_spec)
87+
assert str(check_virus).startswith("check for viruses in ")
88+
8689
a_decision = action.CreateSourceOrDownload(
8790
root=root, left=create_source, right=download_source
8891
)

tests/tests_e3/anod/context_test.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,15 @@ def test_add_anod_action3(self):
137137
# declared
138138
ac = self.create_context()
139139
ac.add_anod_action("spec3", env=ac.default_env, primitive="build")
140-
assert len(ac.tree) == 6, ac.tree.as_dot()
140+
assert len(ac.tree) == 7, ac.tree.as_dot()
141141
result = ac.schedule(ac.always_download_source_resolver)
142-
assert len(result) == 4, result.as_dot()
142+
assert len(result) == 5, result.as_dot()
143143
assert set(result.vertex_data.keys()) == {
144144
"root",
145145
"x86-linux.spec3.build",
146146
"x86-linux.spec3.install",
147147
"x86-linux.spec3.upload_bin",
148+
"x86-linux.spec3.check_virus",
148149
}
149150

150151
def test_add_anod_action4(self):
@@ -153,14 +154,15 @@ def test_add_anod_action4(self):
153154
# build primitive
154155
ac = self.create_context()
155156
ac.add_anod_action("spec4", env=ac.default_env, primitive="build")
156-
assert len(ac.tree) == 6, ac.tree.as_dot()
157+
assert len(ac.tree) == 7, ac.tree.as_dot()
157158
result = ac.schedule(ac.always_download_source_resolver)
158-
assert len(result) == 4, result.as_dot()
159+
assert len(result) == 5, result.as_dot()
159160
assert set(result.vertex_data.keys()) == {
160161
"root",
161162
"x86-linux.spec4.build",
162163
"x86-linux.spec4.install",
163164
"x86-linux.spec4.upload_bin",
165+
"x86-linux.spec4.check_virus",
164166
}
165167

166168
def test_add_anod_action4_2(self):

0 commit comments

Comments
 (0)