@Test public void shouldThrowBadRequestWhenRecipeIsMissing() { User user = new User(); Workspace workspace = new Workspace(); workspace.setId(WORKSPACE_ID); StackV4Request stackRequest = new StackV4Request(); InstanceGroupV4Request instanceGroupV4Request = new InstanceGroupV4Request(); instanceGroupV4Request.setName(INSTANCE_GROUP); instanceGroupV4Request.setRecipeNames(Set.of(RECIPE_NAME)); stackRequest.setInstanceGroups(List.of(instanceGroupV4Request)); doThrow(new NotFoundException("missing recipe")) .when(recipeService).get(NameOrCrn.ofName(RECIPE_NAME), WORKSPACE_ID); expectedException.expect(BadRequestException.class); expectedException.expectMessage("The given recipe does not exist for the instance group \"INSTANCE_GROUP\": RECIPE_NAME"); underTest.createStack(user, workspace, stackRequest, false); verify(blueprintService).updateDefaultBlueprintCollection(WORKSPACE_ID); verify(stackRequestValidator).validate(stackRequest); }
public StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest) { long start = System.currentTimeMillis(); String stackName = stackRequest.getName(); measure(() -> validateRecipeExistenceOnInstanceGroups(stackRequest.getInstanceGroups(), workspace.getId()), LOGGER, "Check that recipes do exist took {} ms"); measure(() -> ensureStackDoesNotExists(stackName, workspace), LOGGER, "Stack does not exist check took {} ms"); Stack stackStub = measure(() -> converterUtil.convert(stackRequest, Stack.class), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); stackStub.setWorkspace(workspace); stackStub.setCreator(user); String platformString = stackStub.getCloudPlatform().toLowerCase(); MDCBuilder.buildMdcContext(stackStub); Stack savedStack; try { Blueprint blueprint = measure(() -> determineBlueprint(stackRequest, workspace), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); Future<StatedImage> imgFromCatalogFuture = determineImageCatalog(stackName, platformString, stackRequest, blueprint, user, workspace); savedStack = transactionService.required(() -> { Stack stack = measure(() -> stackDecorator.decorate(stackStub, stackRequest, user, workspace), LOGGER, "Decorate Stack with data took {} ms"); DetailedEnvironmentResponse environment = measure(() -> ThreadBasedUserCrnProvider.doAsInternalActor(() -> environmentClientService.getByCrn(stack.getEnvironmentCrn())), LOGGER, "Get Environment from Environment service took {} ms"); Credential credential = credentialConverter.convert(environment.getCredential()); CloudCredential cloudCredential = credentialToCloudCredentialConverter.convert(credential); if (stack.getOrchestrator() != null && stack.getOrchestrator().getApiEndpoint() != null) { measure(() -> stackService.validateOrchestrator(stack.getOrchestrator()), LOGGER, "Validate orchestrator took {} ms"); } stack.setUseCcm(environment.getTunnel().useCcm()); stack.setTunnel(environment.getTunnel()); if (stackRequest.getCluster() != null) { measure(() -> setStackType(stack, blueprint), LOGGER, "Set stacktype for stack object took {} ms"); measure(() -> clusterCreationService.validate( stackRequest.getCluster(), cloudCredential, stack, user, workspace, environment, distroxRequest), LOGGER, "Validate cluster rds and autotls took {} ms"); } measure(() -> fillInstanceMetadata(stack), LOGGER, "Fill up instance metadata took {} ms"); StatedImage imgFromCatalog = measure(() -> getImageCatalog(imgFromCatalogFuture), LOGGER, "Select the correct image took {} ms"); Stack newStack = measure(() -> stackService.create( stack, platformString, imgFromCatalog, user, workspace, Optional.ofNullable(stackRequest.getResourceCrn())), LOGGER, "Save the remaining stack data took {} ms" ); try { LOGGER.info("Create cluster enity in the database {} ms with name {}.", stackName); long clusterSaveStart = System.currentTimeMillis(); createClusterIfNeed(user, stackRequest, newStack, stackName, blueprint, environment.getParentEnvironmentCloudPlatform()); LOGGER.info("Cluster save took {} ms", System.currentTimeMillis() - clusterSaveStart); } catch (CloudbreakImageCatalogException | IOException | TransactionExecutionException e) { throw new RuntimeException(e.getMessage(), e); } Stack withSharedServicesIfNeeded = measure(() -> prepareSharedServiceIfNeed(newStack), LOGGER, "Shared service preparation if required took {} ms with name {}.", stackName); measure(() -> assignOwnerRoleOnDataHub(user, stackRequest, newStack), LOGGER, "assignOwnerRoleOnDataHub to stack took {} ms with name {}.", stackName); return withSharedServicesIfNeeded; }); } catch (TransactionExecutionException e) { stackUnderOperationService.off(); if (e.getCause() instanceof DataIntegrityViolationException) { String msg = String.format("Error with resource [%s], error: [%s]", APIResourceType.STACK, getProperSqlErrorMessage((DataIntegrityViolationException) e.getCause())); throw new BadRequestException(msg); } throw new TransactionRuntimeExecutionException(e); } StackV4Response response = measure(() -> converterUtil.convert(savedStack, StackV4Response.class), LOGGER, "Stack response has been created for stack took {} ms with name {}", stackName); LOGGER.info("Generated stack response after creation: {}", JsonUtil.writeValueAsStringSilentSafe(response)); FlowIdentifier flowIdentifier = measure(() -> flowManager.triggerProvisioning(savedStack.getId()), LOGGER, "Stack triggerProvisioning took {} ms with name {}", stackName); response.setFlowIdentifier(flowIdentifier); metricService.submit(STACK_PREPARATION, System.currentTimeMillis() - start); return response; }
StackCreatorService { public StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest) { long start = System.currentTimeMillis(); String stackName = stackRequest.getName(); measure(() -> validateRecipeExistenceOnInstanceGroups(stackRequest.getInstanceGroups(), workspace.getId()), LOGGER, "Check that recipes do exist took {} ms"); measure(() -> ensureStackDoesNotExists(stackName, workspace), LOGGER, "Stack does not exist check took {} ms"); Stack stackStub = measure(() -> converterUtil.convert(stackRequest, Stack.class), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); stackStub.setWorkspace(workspace); stackStub.setCreator(user); String platformString = stackStub.getCloudPlatform().toLowerCase(); MDCBuilder.buildMdcContext(stackStub); Stack savedStack; try { Blueprint blueprint = measure(() -> determineBlueprint(stackRequest, workspace), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); Future<StatedImage> imgFromCatalogFuture = determineImageCatalog(stackName, platformString, stackRequest, blueprint, user, workspace); savedStack = transactionService.required(() -> { Stack stack = measure(() -> stackDecorator.decorate(stackStub, stackRequest, user, workspace), LOGGER, "Decorate Stack with data took {} ms"); DetailedEnvironmentResponse environment = measure(() -> ThreadBasedUserCrnProvider.doAsInternalActor(() -> environmentClientService.getByCrn(stack.getEnvironmentCrn())), LOGGER, "Get Environment from Environment service took {} ms"); Credential credential = credentialConverter.convert(environment.getCredential()); CloudCredential cloudCredential = credentialToCloudCredentialConverter.convert(credential); if (stack.getOrchestrator() != null && stack.getOrchestrator().getApiEndpoint() != null) { measure(() -> stackService.validateOrchestrator(stack.getOrchestrator()), LOGGER, "Validate orchestrator took {} ms"); } stack.setUseCcm(environment.getTunnel().useCcm()); stack.setTunnel(environment.getTunnel()); if (stackRequest.getCluster() != null) { measure(() -> setStackType(stack, blueprint), LOGGER, "Set stacktype for stack object took {} ms"); measure(() -> clusterCreationService.validate( stackRequest.getCluster(), cloudCredential, stack, user, workspace, environment, distroxRequest), LOGGER, "Validate cluster rds and autotls took {} ms"); } measure(() -> fillInstanceMetadata(stack), LOGGER, "Fill up instance metadata took {} ms"); StatedImage imgFromCatalog = measure(() -> getImageCatalog(imgFromCatalogFuture), LOGGER, "Select the correct image took {} ms"); Stack newStack = measure(() -> stackService.create( stack, platformString, imgFromCatalog, user, workspace, Optional.ofNullable(stackRequest.getResourceCrn())), LOGGER, "Save the remaining stack data took {} ms" ); try { LOGGER.info("Create cluster enity in the database {} ms with name {}.", stackName); long clusterSaveStart = System.currentTimeMillis(); createClusterIfNeed(user, stackRequest, newStack, stackName, blueprint, environment.getParentEnvironmentCloudPlatform()); LOGGER.info("Cluster save took {} ms", System.currentTimeMillis() - clusterSaveStart); } catch (CloudbreakImageCatalogException | IOException | TransactionExecutionException e) { throw new RuntimeException(e.getMessage(), e); } Stack withSharedServicesIfNeeded = measure(() -> prepareSharedServiceIfNeed(newStack), LOGGER, "Shared service preparation if required took {} ms with name {}.", stackName); measure(() -> assignOwnerRoleOnDataHub(user, stackRequest, newStack), LOGGER, "assignOwnerRoleOnDataHub to stack took {} ms with name {}.", stackName); return withSharedServicesIfNeeded; }); } catch (TransactionExecutionException e) { stackUnderOperationService.off(); if (e.getCause() instanceof DataIntegrityViolationException) { String msg = String.format("Error with resource [%s], error: [%s]", APIResourceType.STACK, getProperSqlErrorMessage((DataIntegrityViolationException) e.getCause())); throw new BadRequestException(msg); } throw new TransactionRuntimeExecutionException(e); } StackV4Response response = measure(() -> converterUtil.convert(savedStack, StackV4Response.class), LOGGER, "Stack response has been created for stack took {} ms with name {}", stackName); LOGGER.info("Generated stack response after creation: {}", JsonUtil.writeValueAsStringSilentSafe(response)); FlowIdentifier flowIdentifier = measure(() -> flowManager.triggerProvisioning(savedStack.getId()), LOGGER, "Stack triggerProvisioning took {} ms with name {}", stackName); response.setFlowIdentifier(flowIdentifier); metricService.submit(STACK_PREPARATION, System.currentTimeMillis() - start); return response; } }
StackCreatorService { public StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest) { long start = System.currentTimeMillis(); String stackName = stackRequest.getName(); measure(() -> validateRecipeExistenceOnInstanceGroups(stackRequest.getInstanceGroups(), workspace.getId()), LOGGER, "Check that recipes do exist took {} ms"); measure(() -> ensureStackDoesNotExists(stackName, workspace), LOGGER, "Stack does not exist check took {} ms"); Stack stackStub = measure(() -> converterUtil.convert(stackRequest, Stack.class), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); stackStub.setWorkspace(workspace); stackStub.setCreator(user); String platformString = stackStub.getCloudPlatform().toLowerCase(); MDCBuilder.buildMdcContext(stackStub); Stack savedStack; try { Blueprint blueprint = measure(() -> determineBlueprint(stackRequest, workspace), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); Future<StatedImage> imgFromCatalogFuture = determineImageCatalog(stackName, platformString, stackRequest, blueprint, user, workspace); savedStack = transactionService.required(() -> { Stack stack = measure(() -> stackDecorator.decorate(stackStub, stackRequest, user, workspace), LOGGER, "Decorate Stack with data took {} ms"); DetailedEnvironmentResponse environment = measure(() -> ThreadBasedUserCrnProvider.doAsInternalActor(() -> environmentClientService.getByCrn(stack.getEnvironmentCrn())), LOGGER, "Get Environment from Environment service took {} ms"); Credential credential = credentialConverter.convert(environment.getCredential()); CloudCredential cloudCredential = credentialToCloudCredentialConverter.convert(credential); if (stack.getOrchestrator() != null && stack.getOrchestrator().getApiEndpoint() != null) { measure(() -> stackService.validateOrchestrator(stack.getOrchestrator()), LOGGER, "Validate orchestrator took {} ms"); } stack.setUseCcm(environment.getTunnel().useCcm()); stack.setTunnel(environment.getTunnel()); if (stackRequest.getCluster() != null) { measure(() -> setStackType(stack, blueprint), LOGGER, "Set stacktype for stack object took {} ms"); measure(() -> clusterCreationService.validate( stackRequest.getCluster(), cloudCredential, stack, user, workspace, environment, distroxRequest), LOGGER, "Validate cluster rds and autotls took {} ms"); } measure(() -> fillInstanceMetadata(stack), LOGGER, "Fill up instance metadata took {} ms"); StatedImage imgFromCatalog = measure(() -> getImageCatalog(imgFromCatalogFuture), LOGGER, "Select the correct image took {} ms"); Stack newStack = measure(() -> stackService.create( stack, platformString, imgFromCatalog, user, workspace, Optional.ofNullable(stackRequest.getResourceCrn())), LOGGER, "Save the remaining stack data took {} ms" ); try { LOGGER.info("Create cluster enity in the database {} ms with name {}.", stackName); long clusterSaveStart = System.currentTimeMillis(); createClusterIfNeed(user, stackRequest, newStack, stackName, blueprint, environment.getParentEnvironmentCloudPlatform()); LOGGER.info("Cluster save took {} ms", System.currentTimeMillis() - clusterSaveStart); } catch (CloudbreakImageCatalogException | IOException | TransactionExecutionException e) { throw new RuntimeException(e.getMessage(), e); } Stack withSharedServicesIfNeeded = measure(() -> prepareSharedServiceIfNeed(newStack), LOGGER, "Shared service preparation if required took {} ms with name {}.", stackName); measure(() -> assignOwnerRoleOnDataHub(user, stackRequest, newStack), LOGGER, "assignOwnerRoleOnDataHub to stack took {} ms with name {}.", stackName); return withSharedServicesIfNeeded; }); } catch (TransactionExecutionException e) { stackUnderOperationService.off(); if (e.getCause() instanceof DataIntegrityViolationException) { String msg = String.format("Error with resource [%s], error: [%s]", APIResourceType.STACK, getProperSqlErrorMessage((DataIntegrityViolationException) e.getCause())); throw new BadRequestException(msg); } throw new TransactionRuntimeExecutionException(e); } StackV4Response response = measure(() -> converterUtil.convert(savedStack, StackV4Response.class), LOGGER, "Stack response has been created for stack took {} ms with name {}", stackName); LOGGER.info("Generated stack response after creation: {}", JsonUtil.writeValueAsStringSilentSafe(response)); FlowIdentifier flowIdentifier = measure(() -> flowManager.triggerProvisioning(savedStack.getId()), LOGGER, "Stack triggerProvisioning took {} ms with name {}", stackName); response.setFlowIdentifier(flowIdentifier); metricService.submit(STACK_PREPARATION, System.currentTimeMillis() - start); return response; }  }
StackCreatorService { public StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest) { long start = System.currentTimeMillis(); String stackName = stackRequest.getName(); measure(() -> validateRecipeExistenceOnInstanceGroups(stackRequest.getInstanceGroups(), workspace.getId()), LOGGER, "Check that recipes do exist took {} ms"); measure(() -> ensureStackDoesNotExists(stackName, workspace), LOGGER, "Stack does not exist check took {} ms"); Stack stackStub = measure(() -> converterUtil.convert(stackRequest, Stack.class), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); stackStub.setWorkspace(workspace); stackStub.setCreator(user); String platformString = stackStub.getCloudPlatform().toLowerCase(); MDCBuilder.buildMdcContext(stackStub); Stack savedStack; try { Blueprint blueprint = measure(() -> determineBlueprint(stackRequest, workspace), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); Future<StatedImage> imgFromCatalogFuture = determineImageCatalog(stackName, platformString, stackRequest, blueprint, user, workspace); savedStack = transactionService.required(() -> { Stack stack = measure(() -> stackDecorator.decorate(stackStub, stackRequest, user, workspace), LOGGER, "Decorate Stack with data took {} ms"); DetailedEnvironmentResponse environment = measure(() -> ThreadBasedUserCrnProvider.doAsInternalActor(() -> environmentClientService.getByCrn(stack.getEnvironmentCrn())), LOGGER, "Get Environment from Environment service took {} ms"); Credential credential = credentialConverter.convert(environment.getCredential()); CloudCredential cloudCredential = credentialToCloudCredentialConverter.convert(credential); if (stack.getOrchestrator() != null && stack.getOrchestrator().getApiEndpoint() != null) { measure(() -> stackService.validateOrchestrator(stack.getOrchestrator()), LOGGER, "Validate orchestrator took {} ms"); } stack.setUseCcm(environment.getTunnel().useCcm()); stack.setTunnel(environment.getTunnel()); if (stackRequest.getCluster() != null) { measure(() -> setStackType(stack, blueprint), LOGGER, "Set stacktype for stack object took {} ms"); measure(() -> clusterCreationService.validate( stackRequest.getCluster(), cloudCredential, stack, user, workspace, environment, distroxRequest), LOGGER, "Validate cluster rds and autotls took {} ms"); } measure(() -> fillInstanceMetadata(stack), LOGGER, "Fill up instance metadata took {} ms"); StatedImage imgFromCatalog = measure(() -> getImageCatalog(imgFromCatalogFuture), LOGGER, "Select the correct image took {} ms"); Stack newStack = measure(() -> stackService.create( stack, platformString, imgFromCatalog, user, workspace, Optional.ofNullable(stackRequest.getResourceCrn())), LOGGER, "Save the remaining stack data took {} ms" ); try { LOGGER.info("Create cluster enity in the database {} ms with name {}.", stackName); long clusterSaveStart = System.currentTimeMillis(); createClusterIfNeed(user, stackRequest, newStack, stackName, blueprint, environment.getParentEnvironmentCloudPlatform()); LOGGER.info("Cluster save took {} ms", System.currentTimeMillis() - clusterSaveStart); } catch (CloudbreakImageCatalogException | IOException | TransactionExecutionException e) { throw new RuntimeException(e.getMessage(), e); } Stack withSharedServicesIfNeeded = measure(() -> prepareSharedServiceIfNeed(newStack), LOGGER, "Shared service preparation if required took {} ms with name {}.", stackName); measure(() -> assignOwnerRoleOnDataHub(user, stackRequest, newStack), LOGGER, "assignOwnerRoleOnDataHub to stack took {} ms with name {}.", stackName); return withSharedServicesIfNeeded; }); } catch (TransactionExecutionException e) { stackUnderOperationService.off(); if (e.getCause() instanceof DataIntegrityViolationException) { String msg = String.format("Error with resource [%s], error: [%s]", APIResourceType.STACK, getProperSqlErrorMessage((DataIntegrityViolationException) e.getCause())); throw new BadRequestException(msg); } throw new TransactionRuntimeExecutionException(e); } StackV4Response response = measure(() -> converterUtil.convert(savedStack, StackV4Response.class), LOGGER, "Stack response has been created for stack took {} ms with name {}", stackName); LOGGER.info("Generated stack response after creation: {}", JsonUtil.writeValueAsStringSilentSafe(response)); FlowIdentifier flowIdentifier = measure(() -> flowManager.triggerProvisioning(savedStack.getId()), LOGGER, "Stack triggerProvisioning took {} ms with name {}", stackName); response.setFlowIdentifier(flowIdentifier); metricService.submit(STACK_PREPARATION, System.currentTimeMillis() - start); return response; }  StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest); }
StackCreatorService { public StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest) { long start = System.currentTimeMillis(); String stackName = stackRequest.getName(); measure(() -> validateRecipeExistenceOnInstanceGroups(stackRequest.getInstanceGroups(), workspace.getId()), LOGGER, "Check that recipes do exist took {} ms"); measure(() -> ensureStackDoesNotExists(stackName, workspace), LOGGER, "Stack does not exist check took {} ms"); Stack stackStub = measure(() -> converterUtil.convert(stackRequest, Stack.class), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); stackStub.setWorkspace(workspace); stackStub.setCreator(user); String platformString = stackStub.getCloudPlatform().toLowerCase(); MDCBuilder.buildMdcContext(stackStub); Stack savedStack; try { Blueprint blueprint = measure(() -> determineBlueprint(stackRequest, workspace), LOGGER, "Stack request converted to stack took {} ms for stack {}", stackName); Future<StatedImage> imgFromCatalogFuture = determineImageCatalog(stackName, platformString, stackRequest, blueprint, user, workspace); savedStack = transactionService.required(() -> { Stack stack = measure(() -> stackDecorator.decorate(stackStub, stackRequest, user, workspace), LOGGER, "Decorate Stack with data took {} ms"); DetailedEnvironmentResponse environment = measure(() -> ThreadBasedUserCrnProvider.doAsInternalActor(() -> environmentClientService.getByCrn(stack.getEnvironmentCrn())), LOGGER, "Get Environment from Environment service took {} ms"); Credential credential = credentialConverter.convert(environment.getCredential()); CloudCredential cloudCredential = credentialToCloudCredentialConverter.convert(credential); if (stack.getOrchestrator() != null && stack.getOrchestrator().getApiEndpoint() != null) { measure(() -> stackService.validateOrchestrator(stack.getOrchestrator()), LOGGER, "Validate orchestrator took {} ms"); } stack.setUseCcm(environment.getTunnel().useCcm()); stack.setTunnel(environment.getTunnel()); if (stackRequest.getCluster() != null) { measure(() -> setStackType(stack, blueprint), LOGGER, "Set stacktype for stack object took {} ms"); measure(() -> clusterCreationService.validate( stackRequest.getCluster(), cloudCredential, stack, user, workspace, environment, distroxRequest), LOGGER, "Validate cluster rds and autotls took {} ms"); } measure(() -> fillInstanceMetadata(stack), LOGGER, "Fill up instance metadata took {} ms"); StatedImage imgFromCatalog = measure(() -> getImageCatalog(imgFromCatalogFuture), LOGGER, "Select the correct image took {} ms"); Stack newStack = measure(() -> stackService.create( stack, platformString, imgFromCatalog, user, workspace, Optional.ofNullable(stackRequest.getResourceCrn())), LOGGER, "Save the remaining stack data took {} ms" ); try { LOGGER.info("Create cluster enity in the database {} ms with name {}.", stackName); long clusterSaveStart = System.currentTimeMillis(); createClusterIfNeed(user, stackRequest, newStack, stackName, blueprint, environment.getParentEnvironmentCloudPlatform()); LOGGER.info("Cluster save took {} ms", System.currentTimeMillis() - clusterSaveStart); } catch (CloudbreakImageCatalogException | IOException | TransactionExecutionException e) { throw new RuntimeException(e.getMessage(), e); } Stack withSharedServicesIfNeeded = measure(() -> prepareSharedServiceIfNeed(newStack), LOGGER, "Shared service preparation if required took {} ms with name {}.", stackName); measure(() -> assignOwnerRoleOnDataHub(user, stackRequest, newStack), LOGGER, "assignOwnerRoleOnDataHub to stack took {} ms with name {}.", stackName); return withSharedServicesIfNeeded; }); } catch (TransactionExecutionException e) { stackUnderOperationService.off(); if (e.getCause() instanceof DataIntegrityViolationException) { String msg = String.format("Error with resource [%s], error: [%s]", APIResourceType.STACK, getProperSqlErrorMessage((DataIntegrityViolationException) e.getCause())); throw new BadRequestException(msg); } throw new TransactionRuntimeExecutionException(e); } StackV4Response response = measure(() -> converterUtil.convert(savedStack, StackV4Response.class), LOGGER, "Stack response has been created for stack took {} ms with name {}", stackName); LOGGER.info("Generated stack response after creation: {}", JsonUtil.writeValueAsStringSilentSafe(response)); FlowIdentifier flowIdentifier = measure(() -> flowManager.triggerProvisioning(savedStack.getId()), LOGGER, "Stack triggerProvisioning took {} ms with name {}", stackName); response.setFlowIdentifier(flowIdentifier); metricService.submit(STACK_PREPARATION, System.currentTimeMillis() - start); return response; }  StackV4Response createStack(User user, Workspace workspace, StackV4Request stackRequest, boolean distroxRequest);  }