Coverage for scripts / live_release_validation / actions / baseline.py: 100.00%
37 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-10-28 16:19 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-10-28 16:19 +0000
1"""baseline: capture protected CloudFormation and ECR baselines."""
3from __future__ import annotations
5import copy
6import json
7from typing import Any
9from ..context import (
10 _topology_regions,
11)
12from ..inventory import (
13 capture_baseline,
14 collect_project_resources,
15 project_resources_are_absent,
16)
17from ..models import RunContext
18from ..ownership.dynamodb_streams import (
19 _strip_expired_table_streams,
20)
21from ..ownership.ecr import (
22 _strip_baseline_ecr,
23)
24from ..ownership.efs_automatic_backups import (
25 _strip_accepted_efs_automatic_backup_recovery_points,
26)
27from ..ownership.transaction_search import (
28 TRANSACTION_SEARCH_BASELINE_STATE_KEY,
29 _capture_transaction_search_baseline,
30 _validated_transaction_search_baseline,
31)
32from ..ownership.vpc_endpoints import (
33 _strip_deleted_vpc_endpoints,
34)
36_BASELINE_EFS_ACCEPTANCE_STATE_KEY = "baseline_accepted_efs_automatic_backup_recovery_points"
39def action_baseline(ctx: RunContext) -> dict[str, Any]:
40 """Capture protected stacks/ECR and Transaction Search state; reject project leftovers.
42 The Transaction Search record (every regional Region's X-Ray trace segment
43 destination, GCO resource policy, and span log groups) is persisted with
44 the baseline in the same checkpoint write, because teardown restores
45 exactly what it says and a resume must never re-capture state the run
46 already changed.
47 """
48 if ctx.checkpoint.baseline is not None:
49 accepted_efs_backups = ctx.checkpoint.state.get(
50 _BASELINE_EFS_ACCEPTANCE_STATE_KEY,
51 [],
52 )
53 if not isinstance(accepted_efs_backups, list):
54 raise RuntimeError("Checkpoint baseline EFS acceptance evidence must be a list")
55 transaction_search = _validated_transaction_search_baseline(ctx)
56 return {
57 "reused_checkpoint_baseline": True,
58 **ctx.checkpoint.baseline,
59 "accepted_efs_automatic_backup_recovery_points": copy.deepcopy(accepted_efs_backups),
60 "transaction_search": copy.deepcopy(transaction_search),
61 }
63 enabled_regions = ctx.checkpoint.state.get("enabled_regions")
64 if not enabled_regions:
65 raise RuntimeError("Preflight did not record enabled AWS Regions")
66 baseline = capture_baseline(
67 ctx.session,
68 enabled_regions=enabled_regions,
69 ecr_regions=_topology_regions(ctx),
70 protected_stack_names=ctx.settings.protected_stack_names,
71 )
73 project_inventory = collect_project_resources(
74 ctx.session,
75 enabled_regions=enabled_regions,
76 expected_account=ctx.settings.expected_account,
77 project_name=ctx.config.project_name,
78 seed_region=ctx.config.global_region,
79 validation_run_id=ctx.settings.run_id,
80 )
81 disallowed_inventory = _strip_baseline_ecr(project_inventory, baseline)
82 disallowed_inventory, accepted_efs_backups = (
83 _strip_accepted_efs_automatic_backup_recovery_points(
84 ctx,
85 disallowed_inventory,
86 )
87 )
88 disallowed_inventory, accepted_expired_streams = _strip_expired_table_streams(
89 ctx,
90 disallowed_inventory,
91 )
92 disallowed_inventory, accepted_deleted_vpc_endpoints = _strip_deleted_vpc_endpoints(
93 ctx,
94 disallowed_inventory,
95 )
96 if not project_resources_are_absent(disallowed_inventory):
97 raise RuntimeError(
98 "Fresh baseline contains project resources not owned by this run: "
99 + json.dumps(disallowed_inventory, sort_keys=True)
100 )
102 transaction_search = _capture_transaction_search_baseline(ctx)
104 ctx.checkpoint.baseline = baseline
105 ctx.checkpoint.state[_BASELINE_EFS_ACCEPTANCE_STATE_KEY] = copy.deepcopy(accepted_efs_backups)
106 ctx.checkpoint.state[TRANSACTION_SEARCH_BASELINE_STATE_KEY] = copy.deepcopy(transaction_search)
107 ctx.persist()
108 # The accepted-stream evidence rides the action result (report) only; the
109 # persisted checkpoint baseline stays exactly the protected-stack/ECR
110 # capture that final-inventory's compare_baseline expects. The Transaction
111 # Search record lives in checkpoint state for the same reason.
112 return {
113 **baseline,
114 "accepted_efs_automatic_backup_recovery_points": accepted_efs_backups,
115 "accepted_expired_dynamodb_streams": accepted_expired_streams,
116 "accepted_deleted_vpc_endpoints": accepted_deleted_vpc_endpoints,
117 "transaction_search": transaction_search,
118 }