Skip to content

Commit

Permalink
Re-run store_derived_evidence fetchers
Browse files Browse the repository at this point in the history
Ensure store_derived_evidence fetchers are re-run if dependant evidence
is not yet available, this is achieved by get_evidence_dependency,
rather than get_evidence_by_path.
  • Loading branch information
rhyshort committed Aug 16, 2024
1 parent 82e7d0b commit e8a911d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 4 deletions.
14 changes: 10 additions & 4 deletions compliance/evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,17 +863,23 @@ def store_derived_evidence(evidences, target):
For example, ``src/evidence.json``.
"""

def decorator(f):
@wraps(f) # required for preserving the function context
def decorator(fn):
# generate the information for re-running
fetcher = f"{fn.__module__}.{fn.__qualname__}"

@wraps(fn) # required for preserving the function context
def wrapper(self, *args, **kwargs):
target_path = target
if not target_path.startswith("derived/"):
target_path = f"derived/{target_path}"
target_evidence = get_evidence_by_path(target_path)
if self.locker.validate(target_evidence):
return
depends = [get_evidence_by_path(e, self.locker) for e in evidences]
content = f(self, *depends)
depends = [
get_evidence_dependency(e, self.locker, fetcher=fetcher)
for e in evidences
]
content = fn(self, *depends)
target_evidence.set_content(content)
self.locker.add_evidence(target_evidence)

Expand Down
40 changes: 40 additions & 0 deletions test/t_compliance/t_evidence/test_evidence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import unittest
from unittest.mock import MagicMock, create_autospec

from compliance.evidence import store_derived_evidence
from compliance.locker import Locker
from compliance.utils.exceptions import DependencyUnavailableError, StaleEvidenceError


class TestEvidence(unittest.TestCase):

def test_store_derived_evidence_adds_to_rerun(self):
"""
Ensure that when running a fetcher that stores derived evidence
that it is re-run if one of the dependant evidence is not available.
"""
self.locker = create_autospec(Locker)
self.locker.dependency_rerun = []
self.locker.validate.side_effect = [False, StaleEvidenceError]
self.locker.repo_url = "https://my.locker.url"
self.locker.get_evidence_metadata = MagicMock()
self.locker.get_evidence_metadata.return_value = None
self.locker.get_evidence.side_effect = StaleEvidenceError

with self.assertRaises(DependencyUnavailableError):
self.fetch_some_derived_evidence()

self.assertEquals(1, len(self.locker.dependency_rerun))
f = self.fetch_some_derived_evidence
self.assertDictEqual(
self.locker.dependency_rerun[0],
{
"module": f.__module__,
"class": self.__class__.__name__,
"method": f.__name__,
},
)

@store_derived_evidence(["raw/cos/cos_bucket_metadata.json"], target="cos/bar.json")
def fetch_some_derived_evidence(self, cos_metadata):
return "{}"

0 comments on commit e8a911d

Please sign in to comment.