Skip to content

Commit

Permalink
Merge branch 'main' into sysvinit/sensitive-data-tristate
Browse files Browse the repository at this point in the history
  • Loading branch information
elikoga authored Oct 15, 2024
2 parents dd3582e + 09b5eec commit a27c50d
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
## 2.5.1 (unreleased)
---------------------

- fix Component.require_one raising a configuration error with strict=False
- `File` Component: Converted `sensitive_data` flag to a tri-state variable. This allows manual overriding of automatic sensitivity detection logic for file diffs. The new possible states are:
- `None`: Default automatic detection of sensitive data.
- `True`: Always mark the file as sensitive and avoid printing the diff.
Expand All @@ -19,6 +20,8 @@
context. This variable contains a comment block that signals that
the file content is generated by batou. (#356)
- Development: update Sphinx to 5.3.0 to fix readthedocs build failures.
- Component object model: Class variable .instances renamed to ._instances
to avoid collisions with user-applications.

## 2.5.0b3 (2024-08-05)
-----------------------
Expand Down
37 changes: 37 additions & 0 deletions src/batou/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,43 @@ 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, roots):
self = cls()
self.components = []
for component in components:
self.components.append(repr(component.__class__.__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 idx, component in enumerate(self.components):
out_str += f"\n {component}"
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

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."""

Expand Down
8 changes: 4 additions & 4 deletions src/batou/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class Component(object):
#: After the configuration phase, this list is checked for
#: components that have component._prepared == False and
#: warns about them.
instances: List["Component"] = []
_instances: List["Component"] = []

@property
def defdir(self):
Expand Down Expand Up @@ -229,7 +229,7 @@ def __init__(self, namevar=None, **kw):

self._init_breadcrumbs = init_breadcrumbs

Component.instances.append(self)
Component._instances.append(self)
self.timer = batou.utils.Timer(self.__class__.__name__)
# Are any keyword arguments undefined attributes?
# This is a somewhat rough implementation as it allows overriding
Expand Down Expand Up @@ -655,9 +655,9 @@ def require_one(
key, host
)
)
elif len(resources) == 0:
elif len(resources) == 0 and strict:
raise SilentConfigurationError()
return resources[0]
return resources[0] if resources else None

def assert_cmd(self, *args, **kw):
"""Assert that given command returns successfully, raise
Expand Down
32 changes: 30 additions & 2 deletions src/batou/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import batou.vfs
from batou import (
ComponentLoadingError,
ComponentWithUpdateWithoutVerify,
ConfigurationError,
CycleErrorDetected,
DuplicateHostError,
Expand Down Expand Up @@ -492,13 +493,14 @@ def configure(self):

while working_set:
exceptions = []
components_without_verify = []
previous_working_sets.append(working_set.copy())
retry = set()
self.resources.dirty_dependencies.clear()

for root in working_set:
try:
Component.instances.clear()
Component._instances.clear()
self.resources.reset_component_resources(root)
root.overrides = self.overrides.get(root.name, {})
root.prepare()
Expand All @@ -518,8 +520,10 @@ def configure(self):
)
)
else:
# warnings: does not fail the deployment
# 1. unprepared component warning
unprepared_components = []
for component in Component.instances:
for component in Component._instances:
if not component._prepared:
unprepared_components.append(component)
if unprepared_components:
Expand All @@ -531,6 +535,21 @@ def configure(self):
)
# exceptions.append(unused_exception)
output.warn(str(unused_exception))

# 2. a component has .update() but no .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)
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
Expand Down Expand Up @@ -573,6 +592,15 @@ def configure(self):

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.
Expand Down

0 comments on commit a27c50d

Please sign in to comment.