From fb7e9cf2626db135acd65d28c82147a1223a2262 Mon Sep 17 00:00:00 2001 From: Eli Kogan-Wang Date: Tue, 3 Sep 2024 11:19:10 +0200 Subject: [PATCH 1/2] Add warning: If component has update() but no verify() --- src/batou/__init__.py | 35 +++++++++++++++++++++++++++++++++++ src/batou/environment.py | 25 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/batou/__init__.py b/src/batou/__init__.py index 62636c97..5b0743ed 100644 --- a/src/batou/__init__.py +++ b/src/batou/__init__.py @@ -521,6 +521,41 @@ def report(self): output.tabular("Root", self.root_name, red=True) +class ComponentWithUpdateWithoutVerify(ConfigurationError): + """Some components have an update method but no verify method.""" + + sort_key = (5, "without_verify") + + @classmethod + def from_context(cls, components, root): + self = cls() + self.components = [] + for component in components: + self.components.append(repr(component.__class__.__name__)) + self.root_name = root.name + return self + + def __str__(self): + out_str = "Some components have an update method but no verify method:" + for component in self.components: + out_str += f"\n {component}" + out_str += f"\nRoot: {self.root_name}" + out_str += f"\nThe update() method may not be called by batou if the verify() method is missing." + return out_str + + def report(self): + output.error( + f"Some components have an update method but no verify method:" + ) + for component in self.components: + output.line(f" {component}", red=True) + output.tabular("Root", self.root_name, red=True) + output.line( + f"The update() method may not be called by batou if the verify() method is missing.", + red=True, + ) + + class UnsatisfiedResources(ConfigurationError): """Some required resources were never provided.""" diff --git a/src/batou/environment.py b/src/batou/environment.py index 68cc200a..92ba5969 100644 --- a/src/batou/environment.py +++ b/src/batou/environment.py @@ -15,6 +15,7 @@ import batou.vfs from batou import ( ComponentLoadingError, + ComponentWithUpdateWithoutVerify, ConfigurationError, CycleErrorDetected, DuplicateHostError, @@ -518,6 +519,8 @@ def configure(self): ) ) else: + # warnings: does not fail the deployment + # 1. unprepared component warning unprepared_components = [] for component in Component._instances: if not component._prepared: @@ -531,6 +534,28 @@ def configure(self): ) # exceptions.append(unused_exception) output.warn(str(unused_exception)) + + # 2. a component has .update() but no .verify() + components_without_verify = [] + + def has_original_update_method(component): + return type(component).update != Component.update + + def has_original_verify_method(component): + return type(component).verify != Component.verify + + for component in Component._instances: + if not has_original_update_method( + component + ) and has_original_verify_method(component): + components_without_verify.append(component) + if components_without_verify: + component_without_verify_exception = ( + ComponentWithUpdateWithoutVerify.from_context( + components_without_verify, root + ) + ) + output.warn(str(component_without_verify_exception)) # configured this component successfully # we won't have to retry it later continue From faeea2427b3784012c7d5aa5e3cc7e22835d4ca4 Mon Sep 17 00:00:00 2001 From: Eli Kogan-Wang Date: Tue, 10 Sep 2024 10:58:20 +0200 Subject: [PATCH 2/2] fix behaviour of warning --- src/batou/__init__.py | 10 ++++++---- src/batou/environment.py | 33 ++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/batou/__init__.py b/src/batou/__init__.py index 5b0743ed..c79faf3f 100644 --- a/src/batou/__init__.py +++ b/src/batou/__init__.py @@ -527,19 +527,21 @@ class ComponentWithUpdateWithoutVerify(ConfigurationError): sort_key = (5, "without_verify") @classmethod - def from_context(cls, components, root): + def from_context(cls, components, roots): self = cls() self.components = [] for component in components: self.components.append(repr(component.__class__.__name__)) - self.root_name = root.name + self.roots = [] + for root in roots: + self.roots.append(root.name) return self def __str__(self): out_str = "Some components have an update method but no verify method:" - for component in self.components: + for idx, component in enumerate(self.components): out_str += f"\n {component}" - out_str += f"\nRoot: {self.root_name}" + out_str += f"\nRoot: {self.roots[idx]}" out_str += f"\nThe update() method may not be called by batou if the verify() method is missing." return out_str diff --git a/src/batou/environment.py b/src/batou/environment.py index 92ba5969..611a8af6 100644 --- a/src/batou/environment.py +++ b/src/batou/environment.py @@ -493,6 +493,7 @@ def configure(self): while working_set: exceptions = [] + components_without_verify = [] previous_working_sets.append(working_set.copy()) retry = set() self.resources.dirty_dependencies.clear() @@ -536,26 +537,19 @@ def configure(self): output.warn(str(unused_exception)) # 2. a component has .update() but no .verify() - components_without_verify = [] - def has_original_update_method(component): - return type(component).update != Component.update + return type(component).update == Component.update def has_original_verify_method(component): - return type(component).verify != Component.verify + return type(component).verify == Component.verify for component in Component._instances: - if not has_original_update_method( - component - ) and has_original_verify_method(component): - components_without_verify.append(component) - if components_without_verify: - component_without_verify_exception = ( - ComponentWithUpdateWithoutVerify.from_context( - components_without_verify, root - ) - ) - output.warn(str(component_without_verify_exception)) + if ( + not has_original_update_method(component) + and has_original_verify_method(component) + and (component not in components_without_verify) + ): + components_without_verify.append((component, root)) # configured this component successfully # we won't have to retry it later continue @@ -598,6 +592,15 @@ def has_original_verify_method(component): working_set = retry + # warn if a component has .update() but no .verify() + if components_without_verify: + component_without_verify_exception = ( + ComponentWithUpdateWithoutVerify.from_context( + components_without_verify, root + ) + ) + output.warn(str(component_without_verify_exception)) + # We managed to converge on a working set. However, some resource were # provided but never used. We're rather picky here and report this as # an error.