Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions bin/test_yc_ip_hunter.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,34 @@ def test_project_mode_success_blocks_after_auto_isolation(self):
self.assertEqual(hunter.state["auto_protected_folder_ids"], ["folder-1"])
self.assertEqual(hunter.state["status"], "blocked_by_project_isolation")

def test_hybrid_continue_success_returns_ok_when_iteration_limit_ends(self):
hunter = object.__new__(yc.IpHunter)
hunter.config = {
"continue_after_success": True,
"max_iterations": 1,
"cloud_iteration_sleep_seconds": 0,
}
hunter.state = {}
hunter.persist_state = lambda: None
hunter.notify_success = lambda result: None
hunter.iteration_numbers = lambda max_iterations: iter([1])
hunter.ensure_hybrid_address_scope = lambda iteration: ("cloud-1", "folder-1")
hunter.can_delete_hybrid_cloud = lambda cloud_id, folder_id: True
hunter.run_address_rotation_in_cloud = lambda cloud_id, folder_id, iteration: yc.AttemptResult(
ip="198.51.100.10",
zone="ru-central1-a",
address_id="addr-1",
cloud_id=cloud_id,
folder_id=folder_id,
)
sleeps = []
hunter.sleep_backoff = lambda seconds: sleeps.append(seconds)

self.assertEqual(hunter.run_hybrid_rotation(), 0)
self.assertEqual(hunter.state["success"]["ip"], "198.51.100.10")
self.assertEqual(hunter.state["cloud_recreations_done"], 1)
self.assertEqual(sleeps, [0])

def test_telegram_enabled_inside_disabled_parent_still_sends(self):
hunter = object.__new__(yc.IpHunter)
hunter.config = {
Expand Down
24 changes: 24 additions & 0 deletions bin/yc_ip_hunter.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,7 @@ def run_folder_rotation(self) -> int:
base_backoff = float(self.config.get("cooldown_seconds", 15))
max_backoff = float(self.config.get("backoff_max_seconds", 120))
backoff = base_backoff
reserved_any = False

for iteration in self.iteration_numbers(max_iterations):
folder_id = ""
Expand Down Expand Up @@ -961,6 +962,7 @@ def run_folder_rotation(self) -> int:
raise self.step_error("folder rotation", exc) from exc

if result:
reserved_any = True
self.save_success(result)
LOGGER.info(
"Reserved target IP %s in cloud=%s folder=%s address=%s.",
Expand All @@ -983,6 +985,12 @@ def run_folder_rotation(self) -> int:
self.sleep_backoff(float(self.config.get("iteration_sleep_seconds", 10)))
backoff = base_backoff

if reserved_any:
LOGGER.info(
"Search finished after max_iterations=%s with at least one reserved target IP.",
max_iterations,
)
return 0
LOGGER.error("No requested IP reserved after max_iterations=%s.", max_iterations)
return 2

Expand All @@ -991,6 +999,7 @@ def run_cloud_rotation(self) -> int:
base_backoff = float(self.config.get("cooldown_seconds", 15))
max_backoff = float(self.config.get("backoff_max_seconds", 240))
backoff = base_backoff
reserved_any = False

for iteration in self.iteration_numbers(max_iterations):
LOGGER.info("Cloud rotation iteration %s/%s.", iteration, self.iteration_limit_label(max_iterations))
Expand All @@ -1004,6 +1013,7 @@ def run_cloud_rotation(self) -> int:
cloud_id, folder_id = self.create_cloud_cycle(iteration)
result = self.allocate_cloud_batch(cloud_id, folder_id, iteration)
if result:
reserved_any = True
self.save_success(result)
LOGGER.info(
"Reserved target IP %s in cloud=%s folder=%s address=%s.",
Expand Down Expand Up @@ -1044,6 +1054,12 @@ def run_cloud_rotation(self) -> int:
return 2
raise self.step_error("cloud rotation", exc) from exc

if reserved_any:
LOGGER.info(
"Search finished after max_iterations=%s with at least one reserved target IP.",
max_iterations,
)
return 0
LOGGER.error("No requested IP reserved after max_iterations=%s.", max_iterations)
return 2

Expand All @@ -1053,6 +1069,7 @@ def run_hybrid_rotation(self) -> int:
max_backoff = float(self.config.get("backoff_max_seconds", 240))
backoff = base_backoff
use_existing_scope = True
reserved_any = False

for iteration in self.iteration_numbers(max_iterations):
LOGGER.info(
Expand All @@ -1075,6 +1092,7 @@ def run_hybrid_rotation(self) -> int:
managed_cloud = True
result = self.run_address_rotation_in_cloud(cloud_id, folder_id, iteration)
if result:
reserved_any = True
self.save_success(result)
LOGGER.info(
"Reserved target IP %s in cloud=%s folder=%s address=%s.",
Expand Down Expand Up @@ -1147,6 +1165,12 @@ def run_hybrid_rotation(self) -> int:
continue
raise self.step_error("hybrid rotation", exc) from exc

if reserved_any:
LOGGER.info(
"Search finished after max_iterations=%s with at least one reserved target IP.",
max_iterations,
)
return 0
LOGGER.error("No requested IP reserved after max_iterations=%s.", max_iterations)
return 2

Expand Down