WorkspaceRuntimes { @Traced public CompletableFuture<Void> startAsync( WorkspaceImpl workspace, @Nullable String envName, Map<String, String> options) throws ConflictException, NotFoundException, ServerException { TracingTags.WORKSPACE_ID.set(workspace.getId()); final String workspaceId = workspace.getId(); if (isStartRefused.get()) { throw new ConflictException( format( "Start of the workspace '%s' is rejected by the system, " + "no more workspaces are allowed to start", workspace.getName())); } WorkspaceConfigImpl config = workspace.getConfig(); if (config == null) { config = devfileConverter.convert(workspace.getDevfile()); } if (envName == null) { envName = config.getDefaultEnv(); } String infraNamespace = workspace.getAttributes().get(WORKSPACE_INFRASTRUCTURE_NAMESPACE_ATTRIBUTE); if (isNullOrEmpty(infraNamespace)) { throw new ServerException( String.format( "Workspace does not have infrastructure namespace " + "specified. Please set value of '%s' workspace attribute.", WORKSPACE_INFRASTRUCTURE_NAMESPACE_ATTRIBUTE)); } final RuntimeIdentity runtimeId = new RuntimeIdentityImpl( workspaceId, envName, EnvironmentContext.getCurrent().getSubject().getUserId(), infraNamespace); try { InternalEnvironment internalEnv = createInternalEnvironment( config.getEnvironments().get(envName), config.getAttributes(), config.getCommands(), config.getDevfile()); RuntimeContext runtimeContext = infrastructure.prepare(runtimeId, internalEnv); InternalRuntime runtime = runtimeContext.getRuntime(); try (Unlocker ignored = lockService.writeLock(workspaceId)) { final WorkspaceStatus existingStatus = statuses.putIfAbsent(workspaceId, STARTING); if (existingStatus != null) { throw new ConflictException( format( "Could not start workspace '%s' because its state is '%s'", workspaceId, existingStatus)); } setRuntimesId(workspaceId); runtimes.put(workspaceId, runtime); } LOG.info( "Starting workspace '{}/{}' with id '{}' by user '{}'", workspace.getNamespace(), workspace.getName(), workspace.getId(), sessionUserNameOr("undefined")); publishWorkspaceStatusEvent(workspaceId, STARTING, STOPPED, null, options); return CompletableFuture.runAsync( ThreadLocalPropagateContext.wrap(new StartRuntimeTask(workspace, options, runtime)), sharedPool.getExecutor()); } catch (ValidationException e) { LOG.error(e.getLocalizedMessage(), e); throw new ConflictException(e.getLocalizedMessage()); } catch (InfrastructureException e) { LOG.error(e.getLocalizedMessage(), e); throw new ServerException(e.getLocalizedMessage(), e); } } @VisibleForTesting  WorkspaceRuntimes(
      ConcurrentMap<String, InternalRuntime<?>> runtimes,
      EventService eventService,
      Map<String, InternalEnvironmentFactory> envFactories,
      RuntimeInfrastructure infra,
      WorkspaceSharedPool sharedPool,
      WorkspaceDao workspaceDao,
      @SuppressWarnings("unused") DBInitializer ignored,
      ProbeScheduler probeScheduler,
      WorkspaceStatusCache statuses,
      WorkspaceLockService lockService,
      DevfileConverter devfileConverter); @Inject  WorkspaceRuntimes(
      EventService eventService,
      Map<String, InternalEnvironmentFactory> envFactories,
      RuntimeInfrastructure infra,
      WorkspaceSharedPool sharedPool,
      WorkspaceDao workspaceDao,
      @SuppressWarnings("unused") DBInitializer ignored,
      ProbeScheduler probeScheduler,
      WorkspaceStatusCache statuses,
      WorkspaceLockService lockService,
      DevfileConverter devfileConverter); void validate(WorkspaceImpl workspace, @Nullable String envName); String evalInfrastructureNamespace(NamespaceResolutionContext resolutionCtx); String evalLegacyInfrastructureNamespace(NamespaceResolutionContext resolutionContext); boolean isInfrastructureNamespaceValid(String namespaceName); void injectRuntime(WorkspaceImpl workspace); boolean hasRuntime(String workspaceId); InternalRuntime<?> getInternalRuntime(String workspaceId); WorkspaceStatus getStatus(String workspaceId); @Traced CompletableFuture<Void> startAsync(
      WorkspaceImpl workspace, @Nullable String envName, Map<String, String> options); @Traced CompletableFuture<Void> stopAsync(WorkspaceImpl workspace, Map<String, String> options); boolean refuseStart(); Set<String> getRunning(); Set<String> getActive(); Set<String> getActive(String owner); boolean isAnyActive(); Set<String> getInProgress(); Set<String> getInProgress(String owner); boolean isAnyInProgress(); Optional<RuntimeContext> getRuntimeContext(String workspaceId); Set<String> getSupportedRecipes();  }
@Test( expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = "Workspace does not have infrastructure namespace specified. " + "Please set value of 'infrastructureNamespace' workspace attribute.") public void shouldThrowExceptionIfWorkspaceDoesNotHaveInfraNamespaceSpecifiedOnStartAsync() throws Exception { WorkspaceImpl workspace = WorkspaceImpl.builder().setId("workspace123").setDevfile(new DevfileImpl()).build(); runtimes.startAsync(workspace, "env", emptyMap()); }
@Test public void shouldUseInfraNamespaceAttributeOnStartAsync() throws Exception { EnvironmentContext.getCurrent().setSubject(new SubjectImpl("username", "user123", null, false)); WorkspaceImpl workspace = mockWorkspaceWithDevfile("workspace123", "env"); workspace.getAttributes().put(WORKSPACE_INFRASTRUCTURE_NAMESPACE_ATTRIBUTE, "infraNamespace"); RuntimeContext context = mockContext(new RuntimeIdentityImpl("workspace123", "env", "user123", "infraNamespace")); doReturn(context.getEnvironment()).when(testEnvFactory).create(any()); runtimes.startAsync(workspace, null, emptyMap()); ArgumentCaptor<RuntimeIdentity> runtimeIdCaptor = ArgumentCaptor.forClass(RuntimeIdentity.class); verify(infrastructure).prepare(runtimeIdCaptor.capture(), any()); RuntimeIdentity runtimeId = runtimeIdCaptor.getValue(); assertEquals(runtimeId.getInfrastructureNamespace(), "infraNamespace"); }