mirror of
https://github.com/dredx/prole.git
synced 2026-09-24 19:54:32 +00:00
- Introduce `cnpg_placement.py` to handle round-robin node assignments for CloudNativePG clusters. - Implement persistent placement plans with schema normalization and hashing. - Add `load_cnpg_placement_plan` and `save_cnpg_placement_plan` for plan persistence. - Integrate planner with installer to support node-based topology configuration. - Update `actions.py` with placement planning logic, including rebalance support and node eligibility checks. - Extend shell utilities (`init_cloudnative_pg.sh`) for placement-aware CNPG topology adjustments. - Add comprehensive unit tests and integration tests for planner functionality, persistence, and shell environment exports.
108 lines
3.7 KiB
Python
108 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
from knoe.core.cnpg_placement import (
|
|
load_cnpg_placement_plan,
|
|
plan_cnpg_placement,
|
|
save_cnpg_placement_plan,
|
|
)
|
|
|
|
|
|
class TestCnpgPlacementPlanner:
|
|
def test_deterministic_eligible_node_ordering_and_round_robin(self):
|
|
plan = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=5,
|
|
candidate_nodes=[" db-b ", "db-a", "db-b", "db-c"],
|
|
)
|
|
assert plan["eligible_nodes"] == ["db-a", "db-b", "db-c"]
|
|
assert plan["assignments"] == {
|
|
"0": "db-a",
|
|
"1": "db-b",
|
|
"2": "db-c",
|
|
"3": "db-a",
|
|
"4": "db-b",
|
|
}
|
|
|
|
def test_reuses_persisted_plan_when_still_valid(self):
|
|
prior = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=3,
|
|
candidate_nodes=["db-a", "db-b"],
|
|
)
|
|
plan = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=3,
|
|
candidate_nodes=["db-b", "db-a", "db-c"],
|
|
prior_plan=prior,
|
|
)
|
|
assert plan["metadata"]["reused"] is True
|
|
assert plan["metadata"]["regenerated"] is False
|
|
# New eligible node must not reshuffle existing ordinals.
|
|
assert plan["assignments"] == prior["assignments"]
|
|
|
|
def test_regenerates_when_assigned_node_becomes_ineligible(self):
|
|
prior = {
|
|
"cluster_name": "knoe-db",
|
|
"assignments": {"0": "db-a", "1": "db-b", "2": "db-a"},
|
|
}
|
|
plan = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=3,
|
|
candidate_nodes=["db-a", "db-c"],
|
|
prior_plan=prior,
|
|
)
|
|
assert plan["metadata"]["regenerated"] is True
|
|
assert plan["metadata"]["reason"] == "assigned_node_no_longer_eligible"
|
|
assert set(plan["assignments"].values()) <= {"db-a", "db-c"}
|
|
|
|
def test_rebalance_regenerates_even_with_valid_prior(self):
|
|
prior = {
|
|
"cluster_name": "knoe-db",
|
|
"assignments": {"0": "db-a", "1": "db-a", "2": "db-a"},
|
|
}
|
|
plan = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=3,
|
|
candidate_nodes=["db-a", "db-b", "db-c"],
|
|
prior_plan=prior,
|
|
rebalance=True,
|
|
)
|
|
assert plan["metadata"]["regenerated"] is True
|
|
assert plan["metadata"]["reason"] == "rebalance_requested"
|
|
assert plan["assignments"] == {"0": "db-a", "1": "db-b", "2": "db-c"}
|
|
|
|
def test_graceful_when_fewer_eligible_nodes_than_instances(self):
|
|
plan = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=4,
|
|
candidate_nodes=["db-a"],
|
|
)
|
|
assert plan["assignments"] == {
|
|
"0": "db-a",
|
|
"1": "db-a",
|
|
"2": "db-a",
|
|
"3": "db-a",
|
|
}
|
|
|
|
|
|
class TestCnpgPlacementPersistence:
|
|
def test_persisted_plan_can_be_reloaded_and_reused(self, tmp_path):
|
|
plan_path = tmp_path / "cnpg-placement" / "knoe-system-knoe-db.json"
|
|
initial = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=3,
|
|
candidate_nodes=["db-a", "db-b"],
|
|
)
|
|
save_cnpg_placement_plan(plan_path, initial)
|
|
|
|
prior = load_cnpg_placement_plan(plan_path)
|
|
assert prior is not None
|
|
reused = plan_cnpg_placement(
|
|
cluster_name="knoe-db",
|
|
desired_instances=3,
|
|
candidate_nodes=["db-a", "db-b", "db-c"],
|
|
prior_plan=prior,
|
|
)
|
|
assert reused["metadata"]["reused"] is True
|
|
assert reused["assignments"] == initial["assignments"]
|