PodTerminalGcController extends BaseGcController<V1Pod> { @VisibleForTesting boolean isPodTerminal(V1Pod pod, Map<String, Task> currentTasks) { String podName = KubeUtil.getMetadataName(pod.getMetadata()); Task task = currentTasks.get(podName); if (task != null) { if (TaskState.isTerminalState(task.getStatus().getState())) { return clock.isPast(task.getStatus().getTimestamp() + kubeControllerConfiguration.getPodTerminalGracePeriodMs()); } return false; } V1PodStatus status = pod.getStatus(); if (status != null && KubeUtil.isPodPhaseTerminal(status.getPhase())) { return KubeUtil.findFinishedTimestamp(pod) .map(timestamp -> clock.isPast(timestamp + kubeControllerConfiguration.getPodTerminalGracePeriodMs())) .orElse(true); } return false; } @Inject  PodTerminalGcController(
            TitusRuntime titusRuntime,
            LocalScheduler scheduler,
            @Named(POD_TERMINAL_GC_CONTROLLER) FixedIntervalTokenBucketConfiguration tokenBucketConfiguration,
            @Named(POD_TERMINAL_GC_CONTROLLER) ControllerConfiguration controllerConfiguration,
            KubeApiFacade kubeApiFacade,
            KubeControllerConfiguration kubeControllerConfiguration,
            V3JobOperations v3JobOperations
    ); @Override boolean shouldGc(); @Override List<V1Pod> getItemsToGc(); @Override boolean gcItem(V1Pod item); static final String POD_TERMINAL_GC_CONTROLLER; static final String POD_TERMINAL_GC_CONTROLLER_DESCRIPTION; }
@Test void podIsNotTerminal() { when(kubeControllerConfiguration.getPodTerminalGracePeriodMs()).thenReturn(POD_TERMINAL_GRACE_PERIOD); V1Pod pod = new V1Pod() .metadata(new V1ObjectMeta().name(POD_NAME).creationTimestamp(new DateTime(clock.wallTime()))) .status(new V1PodStatus().phase(RUNNING)); TaskStatus taskStatus = TaskStatus.newBuilder() .withState(TaskState.Started) .withTimestamp(clock.wallTime()) .build(); Task task = JobGenerator.oneBatchTask().toBuilder().withStatus(taskStatus).build(); clock.advanceTime(Duration.ofMillis(POD_TERMINAL_GRACE_PERIOD + 1)); Map<String, Task> currentTasks = Collections.singletonMap(POD_NAME, task); Assertions.assertThat(podGcController.isPodTerminal(pod, currentTasks)).isFalse(); }
@Test void podIsTerminalWithoutGracePeriod() { when(kubeControllerConfiguration.getPodTerminalGracePeriodMs()).thenReturn(POD_TERMINAL_GRACE_PERIOD); V1Pod pod = new V1Pod() .metadata(new V1ObjectMeta().name(POD_NAME).creationTimestamp(new DateTime(clock.wallTime()))) .status(new V1PodStatus().phase(RUNNING)); TaskStatus taskStatus = TaskStatus.newBuilder() .withState(TaskState.Started) .withTimestamp(clock.wallTime()) .build(); Task task = JobGenerator.oneBatchTask().toBuilder().withStatus(taskStatus).build(); Map<String, Task> currentTasks = Collections.singletonMap(POD_NAME, task); Assertions.assertThat(podGcController.isPodTerminal(pod, currentTasks)).isFalse(); }
@Test void podIsTerminal() { when(kubeControllerConfiguration.getPodTerminalGracePeriodMs()).thenReturn(POD_TERMINAL_GRACE_PERIOD); V1Pod pod = new V1Pod() .metadata(new V1ObjectMeta().name(POD_NAME).creationTimestamp(new DateTime(clock.wallTime()))) .status(new V1PodStatus().phase(RUNNING)); TaskStatus taskStatus = TaskStatus.newBuilder() .withState(TaskState.Finished) .withTimestamp(clock.wallTime()) .build(); Task task = JobGenerator.oneBatchTask().toBuilder().withStatus(taskStatus).build(); clock.advanceTime(Duration.ofMillis(POD_TERMINAL_GRACE_PERIOD + 1)); Map<String, Task> currentTasks = Collections.singletonMap(POD_NAME, task); Assertions.assertThat(podGcController.isPodTerminal(pod, currentTasks)).isTrue(); }