Enable safe NPM replica convergence
This commit is contained in:
@@ -54,6 +54,46 @@ class ReconciliationPolicy(Protocol):
|
||||
) -> bool: ...
|
||||
|
||||
|
||||
def merge_desired_with_previous(
|
||||
fresh: Iterable[NormalizedObject],
|
||||
previous: Iterable[NormalizedObject],
|
||||
policies: Mapping[str, ReconciliationPolicy] | None = None,
|
||||
) -> list[NormalizedObject]:
|
||||
selected_policies = (
|
||||
DEFAULT_POLICIES
|
||||
if policies is None
|
||||
else policies
|
||||
)
|
||||
|
||||
previous_by_identity = {
|
||||
(object.object_type, object.logical_key): object
|
||||
for object in previous
|
||||
}
|
||||
|
||||
merged: list[NormalizedObject] = []
|
||||
|
||||
for candidate in fresh:
|
||||
identity = (
|
||||
candidate.object_type,
|
||||
candidate.logical_key,
|
||||
)
|
||||
prior = previous_by_identity.get(identity)
|
||||
policy = selected_policies.get(candidate.object_type)
|
||||
|
||||
merger = (
|
||||
getattr(policy, "merge_desired", None)
|
||||
if policy is not None
|
||||
else None
|
||||
)
|
||||
|
||||
if prior is not None and callable(merger):
|
||||
candidate = merger(prior, candidate)
|
||||
|
||||
merged.append(candidate)
|
||||
|
||||
return merged
|
||||
|
||||
|
||||
def _observation_sort_key(
|
||||
observation: Observation,
|
||||
) -> tuple[str, str, str]:
|
||||
@@ -343,6 +383,26 @@ class CertificateNewestPolicy:
|
||||
== self._portable_state(desired)
|
||||
)
|
||||
|
||||
def merge_desired(
|
||||
self,
|
||||
previous: NormalizedObject,
|
||||
fresh: NormalizedObject,
|
||||
) -> NormalizedObject:
|
||||
if (
|
||||
previous.object_type != CERTIFICATES
|
||||
or fresh.object_type != CERTIFICATES
|
||||
or previous.logical_key != fresh.logical_key
|
||||
):
|
||||
raise ReconciliationConflict(
|
||||
"Certificate desired-state merge requires "
|
||||
"matching certificate identities"
|
||||
)
|
||||
|
||||
if self._newest_key(previous) > self._newest_key(fresh):
|
||||
return previous
|
||||
|
||||
return fresh
|
||||
|
||||
@staticmethod
|
||||
def _equivalent_selection_key(
|
||||
object: NormalizedObject,
|
||||
|
||||
Reference in New Issue
Block a user