KubernetesInternalRuntime extends InternalRuntime<KubernetesRuntimeContext<E>> { public CompletableFuture<Void> waitRunningAsync( List<CompletableFuture<?>> toCancelFutures, KubernetesMachineImpl machine) { Span tracingSpan = tracer.buildSpan(WAIT_RUNNING_ASYNC).start(); TracingTags.WORKSPACE_ID.set(tracingSpan, machine.getWorkspaceId()); TracingTags.MACHINE_NAME.set(tracingSpan, machine.getName()); CompletableFuture<Void> waitFuture = namespace.deployments().waitRunningAsync(machine.getPodName()); waitFuture.whenComplete( (res, ex) -> { if (ex != null) { TracingTags.setErrorStatus(tracingSpan, ex); } tracingSpan.finish(); }); toCancelFutures.add(waitFuture); return waitFuture; } @Inject  KubernetesInternalRuntime(
      @Named("che.infra.kubernetes.workspace_start_timeout_min") int workspaceStartTimeoutMin,
      @Named("che.infra.kubernetes.ingress_start_timeout_min") int ingressStartTimeoutMin,
      NoOpURLRewriter urlRewriter,
      UnrecoverablePodEventListenerFactory unrecoverableEventListenerFactory,
      ServersCheckerFactory serverCheckerFactory,
      WorkspaceVolumesStrategy volumesStrategy,
      ProbeScheduler probeScheduler,
      WorkspaceProbesFactory probesFactory,
      RuntimeEventsPublisher eventPublisher,
      KubernetesSharedPool sharedPool,
      KubernetesRuntimeStateCache runtimeStates,
      KubernetesMachineCache machines,
      StartSynchronizerFactory startSynchronizerFactory,
      Set<InternalEnvironmentProvisioner> internalEnvironmentProvisioners,
      KubernetesEnvironmentProvisioner<E> kubernetesEnvironmentProvisioner,
      SidecarToolingProvisioner<E> toolingProvisioner,
      RuntimeHangingDetector runtimeHangingDetector,
      PreviewUrlCommandProvisioner previewUrlCommandProvisioner,
      SecretAsContainerResourceProvisioner secretAsContainerResourceProvisioner,
      KubernetesServerResolverFactory kubernetesServerResolverFactory,
      RuntimeCleaner runtimeCleaner,
      CheNamespace cheNamespace,
      Tracer tracer,
      @Assisted KubernetesRuntimeContext<E> context,
      @Assisted KubernetesNamespace namespace); void scheduleRuntimeStateChecks(); CompletableFuture<Void> waitRunningAsync(
      List<CompletableFuture<?>> toCancelFutures, KubernetesMachineImpl machine); @Override Map<String, ? extends KubernetesMachineImpl> getInternalMachines(); @Override List<? extends Command> getCommands(); @Override Map<String, String> getProperties(); @Override WorkspaceStatus getStatus(); void scheduleServersCheckers(); boolean isConsistent();  }
@Test(expectedExceptions = InfrastructureException.class) public void stopsWaitingAllMachineStartWhenOneMachineStartFailed() throws Exception { final Container container1 = mockContainer(CONTAINER_NAME_1, EXPOSED_PORT_1); final Container container2 = mockContainer(CONTAINER_NAME_2, EXPOSED_PORT_2, INTERNAL_PORT); final ImmutableMap<String, Pod> allPods = ImmutableMap.of(WORKSPACE_POD_NAME, mockPod(ImmutableList.of(container1, container2))); when(k8sEnv.getPodsCopy()).thenReturn(allPods); internalRuntime = spy(internalRuntime); doThrow(IllegalStateException.class) .when(internalRuntime) .waitRunningAsync(any(), argThat(m -> m.getName().equals(M1_NAME))); try { internalRuntime.start(emptyMap()); } catch (Exception rethrow) { verify(deployments).deploy(any(Pod.class)); verify(ingresses).create(any()); verify(services).create(any()); verify(eventService, atLeastOnce()).publish(any()); final List<MachineStatusEvent> events = captureEvents(); assertTrue(events.contains(newEvent(M1_NAME, STARTING))); throw rethrow; } }
@Test( expectedExceptions = RuntimeStartInterruptedException.class, expectedExceptionsMessageRegExp = "Runtime start for identity 'workspace: workspace123, " + "environment: env1, ownerId: id1' is interrupted") public void throwsInfrastructureExceptionWhenMachinesWaitingIsInterrupted() throws Exception { final Thread thread = Thread.currentThread(); internalRuntime = spy(internalRuntime); doReturn(new CompletableFuture<>()).when(internalRuntime).waitRunningAsync(any(), any()); Executors.newSingleThreadScheduledExecutor() .schedule(thread::interrupt, 300, TimeUnit.MILLISECONDS); internalRuntime.start(emptyMap()); }