fix(deploy): model replay 011 predecessor
This commit is contained in:
@@ -517,6 +517,28 @@ DEVICE_PLANE_CONTROL_CORE_FINAL_COMMAND_KINDS = (
|
||||
"infrastructure_service_instance.ensure",
|
||||
"health_observation.record",
|
||||
)
|
||||
DEVICE_PLANE_CONTROL_CORE_REPLAY_011_COMMAND_KINDS = (
|
||||
"owner_scope.ensure",
|
||||
"project.ensure",
|
||||
"collection.ensure",
|
||||
"project_grant.upsert",
|
||||
"adapter_package.ensure",
|
||||
"adapter_version.register",
|
||||
"model_profile.register",
|
||||
"edge.ensure",
|
||||
"route.ensure",
|
||||
"enrollment_intent.ensure",
|
||||
"device.claim",
|
||||
"device.transfer",
|
||||
"discovery.reject",
|
||||
"discovery.expire",
|
||||
"device_credential_binding.upsert",
|
||||
"device_credential_binding.revoke",
|
||||
"device_binding.ensure",
|
||||
"device_binding.revoke",
|
||||
"device_configuration_revision.create",
|
||||
"device_configuration_desired.set",
|
||||
)
|
||||
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TRIGGER_KINDS = (
|
||||
"asset.ensure",
|
||||
"asset_binding.ensure",
|
||||
@@ -16865,6 +16887,19 @@ def device_plane_control_core_migration_replay_database_invariants_match(
|
||||
)
|
||||
|
||||
|
||||
def device_plane_control_core_migration_replay_predecessor_invariants_match(
|
||||
evidence,
|
||||
):
|
||||
return (
|
||||
evidence["invalidCommandKindCount"] == 0
|
||||
and evidence["triggeringReceiptCount"] >= 1
|
||||
and not evidence["constraintValidated"]
|
||||
and not evidence["constraintCoversFinalKinds"]
|
||||
and evidence["constraintMatchesReplay011Kinds"]
|
||||
and evidence["hostTelemetryTableAbsent"]
|
||||
)
|
||||
|
||||
|
||||
def emit_device_plane_control_core_migration_replay_database_evidence(
|
||||
evidence,
|
||||
):
|
||||
@@ -16891,15 +16926,26 @@ def emit_device_plane_control_core_migration_replay_database_evidence(
|
||||
"device_control_core_host_telemetry_table_absent="
|
||||
f"{boolean(evidence['hostTelemetryTableAbsent'])}"
|
||||
)
|
||||
print(
|
||||
"device_control_core_constraint_matches_replay_011_kinds="
|
||||
f"{boolean(evidence['constraintMatchesReplay011Kinds'])}"
|
||||
)
|
||||
print(
|
||||
"device_control_core_recovery_044_ready="
|
||||
f"{boolean(evidence['recovery044Ready'])}"
|
||||
)
|
||||
print(
|
||||
"device_control_core_recovery_final_state_ready="
|
||||
f"{boolean(evidence['finalStateReady'])}"
|
||||
)
|
||||
|
||||
|
||||
def collect_device_plane_control_core_migration_replay_database_evidence(
|
||||
enforce_recovery_invariants=True,
|
||||
expected_state="final",
|
||||
):
|
||||
if expected_state not in ("final", "replay-011-predecessor"):
|
||||
die("Device Control Core migration recovery database state is invalid")
|
||||
postgres_ids = device_plane_service_container_ids("device-postgres")
|
||||
if len(postgres_ids) != 1:
|
||||
die("Device Control Core migration recovery PostgreSQL is missing")
|
||||
@@ -16911,14 +16957,32 @@ def collect_device_plane_control_core_migration_replay_database_evidence(
|
||||
"'" + value.replace("'", "''") + "'"
|
||||
for value in DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TRIGGER_KINDS
|
||||
)
|
||||
replay_011 = ",".join(
|
||||
"'" + value.replace("'", "''") + "'"
|
||||
for value in DEVICE_PLANE_CONTROL_CORE_REPLAY_011_COMMAND_KINDS
|
||||
)
|
||||
query = f"""
|
||||
with constraint_state as (
|
||||
select convalidated,
|
||||
pg_get_constraintdef(c.oid) as definition,
|
||||
(select bool_and(pg_get_constraintdef(c.oid) like '%' || kind || '%')
|
||||
from unnest(array[{allowed}]::text[]) as kind) as covers_final
|
||||
from pg_constraint c
|
||||
where c.conrelid = 'public.device_management_command_receipts'::regclass
|
||||
and c.conname = 'device_management_command_receipts_command_kind_check'
|
||||
),
|
||||
constraint_literals as (
|
||||
select array_agg((matched.value)[1] order by (matched.value)[1]) as values
|
||||
from constraint_state
|
||||
cross join lateral regexp_matches(
|
||||
constraint_state.definition,
|
||||
'''([^'']+)''',
|
||||
'g'
|
||||
) as matched(value)
|
||||
),
|
||||
expected_replay_011 as (
|
||||
select array_agg(kind order by kind) as values
|
||||
from unnest(array[{replay_011}]::text[]) as expected(kind)
|
||||
)
|
||||
select (
|
||||
select count(*)
|
||||
@@ -16933,7 +16997,12 @@ select (
|
||||
coalesce((select convalidated::text from constraint_state), 'missing'),
|
||||
coalesce((select covers_final::text from constraint_state), 'false'),
|
||||
(to_regclass('public.device_infrastructure_host_telemetry_samples')
|
||||
is null)::text
|
||||
is null)::text,
|
||||
coalesce((
|
||||
select constraint_literals.values = expected_replay_011.values
|
||||
from constraint_literals
|
||||
cross join expected_replay_011
|
||||
), false)::text
|
||||
""".strip()
|
||||
result = subprocess.run(
|
||||
[
|
||||
@@ -16963,12 +17032,13 @@ select (
|
||||
if (
|
||||
result.returncode != 0
|
||||
or result.stderr.strip()
|
||||
or len(values) != 5
|
||||
or len(values) != 6
|
||||
or not re.fullmatch(r"[0-9]+", values[0])
|
||||
or not re.fullmatch(r"[0-9]+", values[1])
|
||||
or values[2] not in ("true", "false", "missing")
|
||||
or values[3] not in ("true", "false")
|
||||
or values[4] not in ("true", "false")
|
||||
or values[5] not in ("true", "false")
|
||||
):
|
||||
die("Device Control Core migration recovery database read failed")
|
||||
evidence = {
|
||||
@@ -16977,14 +17047,25 @@ select (
|
||||
"constraintValidated": values[2] == "true",
|
||||
"constraintCoversFinalKinds": values[3] == "true",
|
||||
"hostTelemetryTableAbsent": values[4] == "true",
|
||||
"constraintMatchesReplay011Kinds": values[5] == "true",
|
||||
"query": query,
|
||||
}
|
||||
evidence["recovery044Ready"] = (
|
||||
evidence["finalStateReady"] = (
|
||||
device_plane_control_core_migration_replay_database_invariants_match(
|
||||
evidence
|
||||
)
|
||||
)
|
||||
if enforce_recovery_invariants and not evidence["recovery044Ready"]:
|
||||
evidence["recovery044Ready"] = (
|
||||
device_plane_control_core_migration_replay_predecessor_invariants_match(
|
||||
evidence
|
||||
)
|
||||
)
|
||||
expected_ready = (
|
||||
evidence["recovery044Ready"]
|
||||
if expected_state == "replay-011-predecessor"
|
||||
else evidence["finalStateReady"]
|
||||
)
|
||||
if enforce_recovery_invariants and not expected_ready:
|
||||
emit_device_plane_control_core_migration_replay_database_evidence(
|
||||
evidence
|
||||
)
|
||||
@@ -17169,7 +17250,9 @@ def validate_device_plane_control_core_migration_replay_recovery_evidence(
|
||||
if image_id != DEVICE_PLANE_CONTROL_CORE_V3_PREAPPLY_IMAGE_ID:
|
||||
die("Device Control Core migration recovery predecessor image is missing")
|
||||
database = (
|
||||
collect_device_plane_control_core_migration_replay_database_evidence()
|
||||
collect_device_plane_control_core_migration_replay_database_evidence(
|
||||
expected_state="replay-011-predecessor",
|
||||
)
|
||||
)
|
||||
return {
|
||||
"mode": descriptor["mode"],
|
||||
@@ -17222,7 +17305,9 @@ def accept_device_plane_control_core_migration_replay_recovery():
|
||||
):
|
||||
die("Device Control Core migration recovery did not converge")
|
||||
database = (
|
||||
collect_device_plane_control_core_migration_replay_database_evidence()
|
||||
collect_device_plane_control_core_migration_replay_database_evidence(
|
||||
expected_state="final",
|
||||
)
|
||||
)
|
||||
validate_device_manager_control_plane_runtime(
|
||||
require_edge_channel=True,
|
||||
@@ -32231,9 +32316,16 @@ def plan_artifact(artifact):
|
||||
f"{database['triggeringReceiptCount']}"
|
||||
)
|
||||
print(
|
||||
"device_control_core_final_constraint="
|
||||
"device_control_core_current_constraint="
|
||||
"not-validated:exact-migration-011-command-kinds"
|
||||
)
|
||||
print(
|
||||
"device_control_core_target_constraint="
|
||||
"validated:covers-migration-016-command-kinds"
|
||||
)
|
||||
emit_device_plane_control_core_migration_replay_database_evidence(
|
||||
database
|
||||
)
|
||||
print("device_postgres_row_mutation=none")
|
||||
print("device_postgres_telemetry_table=absent")
|
||||
print(
|
||||
|
||||
Reference in New Issue
Block a user