Skip to content

Commit 9d880c4

Browse files
committed
do not count batches on emtpy namespaces and added test
1 parent c41800c commit 9d880c4

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

robusta_krr/core/integrations/kubernetes/__init__.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,16 +563,17 @@ async def _list_all_jobs(self) -> list[K8sObjectData]:
563563
limit=settings.discovery_job_batch_size,
564564
continue_ref=continue_ref,
565565
)
566-
batch_count += 1
567566
continue_ref = next_continue_ref
568567

569-
# refreshed continue token
570568
if not jobs_batch and continue_ref:
569+
# refreshed continue token, count error batches
570+
batch_count += 1
571571
continue
572572
if not jobs_batch:
573-
# no more jobs to batch
573+
# no more jobs to batch do not count empty batches
574574
break
575-
575+
576+
batch_count += 1
576577
for job in jobs_batch:
577578
if self._is_job_owned_by_cronjob(job):
578579
continue
@@ -632,16 +633,17 @@ async def _list_all_groupedjobs(self) -> list[K8sObjectData]:
632633
continue_ref=continue_ref,
633634
)
634635

635-
batch_count += 1
636636
continue_ref = next_continue_ref
637637

638-
# refreshed continue token
639638
if not jobs_batch and continue_ref:
639+
# refreshed continue token, count error batches
640+
batch_count += 1
640641
continue
641642
if not jobs_batch:
642-
# no more jobs to batch
643+
# no more jobs to batch do not count empty batches
643644
break
644645

646+
batch_count += 1
645647
for job in jobs_batch:
646648
if not job.metadata.labels or self._is_job_owned_by_cronjob(job) or not self._is_job_grouped(job):
647649
continue

robusta_krr/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,15 @@ def run_strategy(
233233
rich_help_panel="Job Grouping Settings",
234234
),
235235
discovery_job_batch_size: int = typer.Option(
236-
250,
236+
5000,
237237
"--discovery-job-batch-size",
238-
help="Batch size for Kubernetes job API calls (default: 1000).",
238+
help="Batch size for Kubernetes job API calls (default: 5000).",
239239
rich_help_panel="Job Discovery Settings",
240240
),
241241
discovery_job_max_batches: int = typer.Option(
242242
100,
243243
"--discovery-job-max-batches",
244-
help="Maximum number of job batches to process to prevent infinite loops (default: 50).",
244+
help="Maximum number of job batches to process to prevent infinite loops (default: 100).",
245245
rich_help_panel="Job Discovery Settings",
246246
),
247247
format: str = typer.Option(

tests/test_grouped_jobs.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,59 @@ def mock_build_scannable_object(item, container, kind):
341341

342342
assert len(api_group._api_resource._grouped_jobs) == 1
343343
assert api_group._api_resource._grouped_jobs[0].name == "job-2"
344+
345+
346+
@pytest.mark.asyncio
347+
async def test_groupedjobs_respects_global_batch_limit_across_namespaces(mock_kubernetes_loader, mock_config):
348+
"""Verify batch_count is global: when limit reached, subsequent namespaces are not processed."""
349+
mock_config.namespaces = ["ns-1", "ns-2"]
350+
mock_config.discovery_job_max_batches = 1
351+
352+
calls = []
353+
354+
async def mock_batched_method(*args, **kwargs):
355+
calls.append(kwargs.get("namespace"))
356+
# return empty batch and no continue token
357+
return ([], None)
358+
359+
mock_kubernetes_loader._list_namespaced_or_global_objects_batched = mock_batched_method
360+
361+
with patch("robusta_krr.core.integrations.kubernetes.settings", mock_config):
362+
result = await mock_kubernetes_loader._list_all_groupedjobs()
363+
364+
# No results; with empty batches not counted, both namespaces are attempted
365+
assert result == []
366+
assert calls == ["ns-1", "ns-2"]
367+
368+
369+
@pytest.mark.asyncio
370+
async def test_groupedjobs_calls_each_explicit_namespace(mock_kubernetes_loader, mock_config):
371+
"""Ensure explicit namespaces list is iterated and passed to the batched call."""
372+
mock_config.namespaces = ["namespace-a", "namespace-b"]
373+
mock_config.discovery_job_max_batches = 10
374+
375+
seen_namespaces = []
376+
377+
# Return one simple job per call and terminate with no continue token
378+
async def mock_batched_method(*args, **kwargs):
379+
ns = kwargs.get("namespace")
380+
seen_namespaces.append(ns)
381+
job = create_mock_job("job-1", ns if ns != "*" else "default", {"app": "frontend"})
382+
return ([job], None)
383+
384+
mock_kubernetes_loader._list_namespaced_or_global_objects_batched = mock_batched_method
385+
386+
def mock_build_scannable_object(item, container, kind):
387+
obj = MagicMock()
388+
obj._api_resource = MagicMock()
389+
obj.container = container.name
390+
return obj
391+
392+
mock_kubernetes_loader._ClusterLoader__build_scannable_object = mock_build_scannable_object
393+
394+
with patch("robusta_krr.core.integrations.kubernetes.settings", mock_config):
395+
result = await mock_kubernetes_loader._list_all_groupedjobs()
396+
397+
# We expect one grouped object per namespace
398+
assert len(result) == 2
399+
assert set(seen_namespaces) == {"namespace-a", "namespace-b"}

0 commit comments

Comments
 (0)