Enable safe NPM replica convergence
This commit is contained in:
@@ -240,6 +240,109 @@ class ObservationAuthorityTests(unittest.TestCase):
|
||||
)
|
||||
)
|
||||
|
||||
def test_persisted_newer_certificate_cannot_regress_to_older_live_certificate(
|
||||
self,
|
||||
):
|
||||
endpoint = Endpoint(
|
||||
"npm",
|
||||
"192.168.1.3:81",
|
||||
)
|
||||
|
||||
live = FakeAdapter(
|
||||
endpoint=endpoint,
|
||||
capabilities=capability_set(
|
||||
CERTIFICATES,
|
||||
apply=True,
|
||||
),
|
||||
discovered={
|
||||
CERTIFICATES: [
|
||||
discovered_certificate(
|
||||
"20",
|
||||
valid_from=(
|
||||
"2026-09-15T00:00:00+00:00"
|
||||
),
|
||||
expires_on=(
|
||||
"2026-12-15T00:00:00+00:00"
|
||||
),
|
||||
)
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
persisted = normalized_certificate(
|
||||
"99",
|
||||
valid_from=(
|
||||
"2026-09-19T00:00:00+00:00"
|
||||
),
|
||||
expires_on=(
|
||||
"2026-12-19T00:00:00+00:00"
|
||||
),
|
||||
)
|
||||
|
||||
persisted = NormalizedObject(
|
||||
object_type=persisted.object_type,
|
||||
logical_key=persisted.logical_key,
|
||||
payload=dict(persisted.payload),
|
||||
)
|
||||
|
||||
with SQLiteStateStore(":memory:") as store:
|
||||
store.replace_desired_state(
|
||||
CERTIFICATES,
|
||||
[persisted],
|
||||
T1,
|
||||
)
|
||||
|
||||
result = discover_reconcile_plan(
|
||||
[live],
|
||||
store,
|
||||
target_ip="192.168.1.101",
|
||||
run_at=T2,
|
||||
)
|
||||
|
||||
stored = store.load_desired_state(
|
||||
CERTIFICATES
|
||||
)
|
||||
|
||||
certificates = [
|
||||
object
|
||||
for object in result.desired
|
||||
if object.object_type == CERTIFICATES
|
||||
]
|
||||
|
||||
self.assertEqual(len(certificates), 1)
|
||||
self.assertEqual(
|
||||
certificates[0].payload["valid_from"],
|
||||
"2026-09-19T00:00:00+00:00",
|
||||
)
|
||||
self.assertEqual(
|
||||
certificates[0].payload["expires_on"],
|
||||
"2026-12-19T00:00:00+00:00",
|
||||
)
|
||||
|
||||
self.assertEqual(len(stored), 1)
|
||||
self.assertEqual(
|
||||
stored[0].object,
|
||||
persisted,
|
||||
)
|
||||
|
||||
self.assertEqual(len(result.plans), 1)
|
||||
self.assertEqual(
|
||||
result.plans[0].endpoint_id,
|
||||
endpoint.identity,
|
||||
)
|
||||
self.assertEqual(
|
||||
len(result.plans[0].actions),
|
||||
1,
|
||||
)
|
||||
self.assertEqual(
|
||||
result.plans[0].actions[0].operation.value,
|
||||
"replace",
|
||||
)
|
||||
self.assertEqual(
|
||||
result.plans[0].actions[0].desired,
|
||||
persisted,
|
||||
)
|
||||
|
||||
def test_all_failed_sources_preserve_persisted_desired_without_planning(self):
|
||||
npm_endpoint = Endpoint(
|
||||
"npm",
|
||||
|
||||
Reference in New Issue
Block a user