diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java index 8ee5fc9b9b6..893d2f0b547 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java @@ -32,10 +32,7 @@ public interface Factory { /** Returns creator of this factory instance. */ Author getCreator(); - /** - * Returns a workspace configuration of this factory instance, it is mandatory for every factory - * instance. - */ + /** Returns a workspace configuration of this factory instance. */ WorkspaceConfig getWorkspace(); /** Returns restrictions of this factory instance. */ diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Component.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Component.java index f2deb98d985..26ac5d2011d 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Component.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Component.java @@ -90,7 +90,7 @@ public interface Component { * optional and applicable only for 'dockerimage' component type. `CHE_PROJECTS_ROOT` environment * variable should contains a path where projects sources are mount. */ - boolean getMountSources(); + Boolean getMountSources(); /** * Returns the command to run in the dockerimage component instead of the default one provided in diff --git a/dashboard/src/app/factories/load-factory/load-factory.controller.ts b/dashboard/src/app/factories/load-factory/load-factory.controller.ts index a6bf8375117..53aea38aaab 100644 --- a/dashboard/src/app/factories/load-factory/load-factory.controller.ts +++ b/dashboard/src/app/factories/load-factory/load-factory.controller.ts @@ -11,6 +11,7 @@ */ 'use strict'; import {CheAPI} from '../../../components/api/che-api.factory'; +import {CheWorkspace} from '../../../components/api/workspace/che-workspace.factory'; import {LoadFactoryService, FactoryLoadingStep} from './load-factory.service'; import {CheNotification} from '../../../components/notification/che-notification.factory'; import {RouteHistory} from '../../../components/routing/route-history.service'; @@ -25,9 +26,10 @@ const WS_AGENT_STEP: number = 4; */ export class LoadFactoryController { - static $inject = ['cheAPI', 'cheJsonRpcApi', '$route', '$timeout', '$mdDialog', 'loadFactoryService', 'lodash', 'cheNotification', '$location', 'routeHistory', '$window', 'loadFactoryService']; + static $inject = ['cheAPI', 'cheWorkspace','cheJsonRpcApi', '$route', '$timeout', '$mdDialog', 'loadFactoryService', 'lodash', 'cheNotification', '$location', 'routeHistory', '$window', 'loadFactoryService']; private cheAPI: CheAPI; + cheWorkspace: CheWorkspace; private $timeout: ng.ITimeoutService; private $mdDialog: ng.material.IDialogService; private loadFactoryService: LoadFactoryService; @@ -49,6 +51,7 @@ export class LoadFactoryController { * Default constructor that is using resource */ constructor(cheAPI: CheAPI, + cheWorkspace: CheWorkspace, cheJsonRpcApi: CheJsonRpcApi, $route: ng.route.IRouteService, $timeout: ng.ITimeoutService, @@ -60,6 +63,7 @@ export class LoadFactoryController { routeHistory: RouteHistory, $window: ng.IWindowService) { this.cheAPI = cheAPI; + this.cheWorkspace = cheWorkspace; this.$timeout = $timeout; this.$mdDialog = $mdDialog; this.loadFactoryService = loadFactoryService; @@ -121,9 +125,9 @@ export class LoadFactoryController { } // check factory contains compatible workspace config: - if (!this.factory.workspace || !this.isSupportedVersion()) { + if (!(Boolean(this.factory.workspace) !== Boolean(this.factory.devfile)) || !this.isSupportedVersion()) { this.getLoadingSteps()[this.getCurrentProgressStep()].hasError = true; - this.getLoadingSteps()[this.getCurrentProgressStep()].logs = 'Factory has no compatible workspace config.'; + this.getLoadingSteps()[this.getCurrentProgressStep()].logs = 'Factory has no compatible workspace config or devfile.'; } else { this.loadFactoryService.goToNextStep(); this.$timeout(() => { @@ -272,20 +276,35 @@ export class LoadFactoryController { * Create workspace from factory config. */ createWorkspace(): any { - let config = this.factory.workspace; - // set factory attribute: - let attrs = {factoryId: this.factory.id}; - config.name = this.getWorkspaceName(config.name); - - // todo: fix account when ready: - let creationPromise = this.cheAPI.getWorkspace().createWorkspaceFromConfig(null, config, attrs); - creationPromise.then((data: any) => { - this.$timeout(() => { - this.startWorkspace(data); - }, 1000); - }, (error: any) => { - this.handleError(error); - }); + if (this.factory.workspace) { + let config = this.factory.workspace; + // set factory attribute: + let attrs = {factoryId: this.factory.id}; + config.name = this.getWorkspaceName(config.name); + + // todo: fix account when ready: + let creationPromise = this.cheAPI.getWorkspace().createWorkspaceFromConfig(null, config, attrs); + creationPromise.then((data: any) => { + this.$timeout(() => { + this.startWorkspace(data); + }, 1000); + }, (error: any) => { + this.handleError(error); + }); + } else if (this.factory.devfile) { + let devfile = this.factory.devfile; + // set factory attribute: + let attrs = {factoryId: this.factory.id}; + + let creationPromise = this.cheAPI.getWorkspace().createWorkspaceFromDevfile(null, devfile, attrs); + creationPromise.then((data: any) => { + this.$timeout(() => { + this.startWorkspace(data); + }, 1000); + }, (error: any) => { + this.handleError(error); + }); + } } /** @@ -340,7 +359,7 @@ export class LoadFactoryController { * @param workspace */ doStartWorkspace(workspace: che.IWorkspace): void { - let startWorkspacePromise = this.cheAPI.getWorkspace().startWorkspace(workspace.id, workspace.config.defaultEnv); + let startWorkspacePromise = this.cheAPI.getWorkspace().startWorkspace(workspace.id); this.loadFactoryService.goToNextStep(); startWorkspacePromise.then((data: any) => { @@ -668,7 +687,7 @@ export class LoadFactoryController { * @returns {string} IDE application link */ getIDELink() { - return '/ide/' + this.workspace.namespace + '/' + this.workspace.config.name; + return '/ide/' + this.workspace.namespace + '/' + this.cheWorkspace.getWorkspaceDataManager().getName(this.workspace); } /** diff --git a/dashboard/src/components/widget/accordion/che-accordion.directive.ts b/dashboard/src/components/widget/accordion/che-accordion.directive.ts index cfcdface200..24d7ce874ee 100644 --- a/dashboard/src/components/widget/accordion/che-accordion.directive.ts +++ b/dashboard/src/components/widget/accordion/che-accordion.directive.ts @@ -57,8 +57,12 @@ export class CheAccordion implements ng.IDirective { continue; } - let siblingBodyEl = siblingEl.find('.che-accordion-body'), - siblingBodyHeight = siblingBodyEl[0].clientHeight; + let siblingBodyEl = siblingEl.find('.che-accordion-body'); + if (siblingBodyEl.length === 0) { + continue; + } + + let siblingBodyHeight = siblingBodyEl[0].clientHeight; siblingBodyEl.css('height', siblingBodyHeight); panesToClose.push(siblingEl); } diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/DockerimageComponentToWorkspaceApplier.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/DockerimageComponentToWorkspaceApplier.java index efb4e5d07be..a924e17f586 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/DockerimageComponentToWorkspaceApplier.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/DockerimageComponentToWorkspaceApplier.java @@ -128,7 +128,7 @@ public void apply( .getVolumes() .put(v.getName(), new VolumeImpl().withPath(v.getContainerPath()))); - if (dockerimageComponent.getMountSources()) { + if (Boolean.TRUE.equals(dockerimageComponent.getMountSources())) { machineConfig .getVolumes() .put(PROJECTS_VOLUME_NAME, new VolumeImpl().withPath(projectFolderPath)); diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/KubernetesComponentToWorkspaceApplier.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/KubernetesComponentToWorkspaceApplier.java index c3528be96ae..02143b581fc 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/KubernetesComponentToWorkspaceApplier.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/devfile/KubernetesComponentToWorkspaceApplier.java @@ -146,7 +146,7 @@ public void apply( estimateCommandsMachineName(workspaceConfig, k8sComponent, podsData); - if (k8sComponent.getMountSources()) { + if (Boolean.TRUE.equals(k8sComponent.getMountSources())) { applyProjectsVolumes(podsData, componentObjects); } diff --git a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/factory/TestFactoryInitializer.java b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/factory/TestFactoryInitializer.java index 69861f197a6..0a1b22531b1 100644 --- a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/factory/TestFactoryInitializer.java +++ b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/factory/TestFactoryInitializer.java @@ -31,6 +31,7 @@ import org.eclipse.che.api.factory.shared.dto.IdeDto; import org.eclipse.che.api.factory.shared.dto.PoliciesDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; import org.eclipse.che.commons.lang.IoUtil; import org.eclipse.che.commons.lang.NameGenerator; import org.eclipse.che.dto.server.DtoFactory; @@ -177,6 +178,21 @@ public FactoryDto withV(String v) { return factoryDto.withV(v); } + @Override + public DevfileDto getDevfile() { + return factoryDto.getDevfile(); + } + + @Override + public void setDevfile(DevfileDto workspace) { + factoryDto.setDevfile(workspace); + } + + @Override + public FactoryDto withDevfile(DevfileDto devfileDto) { + return factoryDto.withDevfile(devfileDto); + } + @Override public WorkspaceConfigDto getWorkspace() { return factoryDto.getWorkspace(); diff --git a/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java b/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java index efe3963acce..2ef76938bbe 100644 --- a/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java +++ b/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolver.java @@ -15,6 +15,7 @@ import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME; import static org.eclipse.che.dto.server.DtoFactory.newDto; +import java.util.Collections; import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; @@ -27,6 +28,7 @@ import org.eclipse.che.api.factory.shared.dto.FactoryDto; import org.eclipse.che.api.workspace.server.devfile.URLFetcher; import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto; /** * Provides Factory Parameters resolver for github repositories. @@ -105,21 +107,28 @@ public FactoryDto createFactory(@NotNull final Map factoryParame newDto(FactoryDto.class) .withV(CURRENT_VERSION) .withSource("repo"))); - // add workspace configuration if not defined - if (factory.getWorkspace() == null) { - factory.setWorkspace( - urlFactoryBuilder.buildDefaultWorkspaceConfig(githubUrl.getRepository())); - } - // apply merging operation from existing and computed settings if needed - return projectConfigDtoMerger.merge( - factory, - () -> { - // Compute project configuration - return newDto(ProjectConfigDto.class) - .withSource(githubSourceStorageBuilder.build(githubUrl)) - .withName(githubUrl.getRepository()) - .withPath("/".concat(githubUrl.getRepository())); - }); + if (factory.getWorkspace() != null) { + return projectConfigDtoMerger.merge( + factory, + () -> { + // Compute project configuration + return newDto(ProjectConfigDto.class) + .withSource(githubSourceStorageBuilder.buildWorkspaceConfigSource(githubUrl)) + .withName(githubUrl.getRepository()) + .withPath("/".concat(githubUrl.getRepository())); + }); + } else if (factory.getDevfile() == null) { + // initialize default devfile and github project + factory.setDevfile(urlFactoryBuilder.buildDefaultDevfile(githubUrl.getRepository())); + factory + .getDevfile() + .setProjects( + Collections.singletonList( + newDto(ProjectDto.class) + .withSource(githubSourceStorageBuilder.buildDevfileSource(githubUrl)) + .withName(githubUrl.getRepository()))); + } + return factory; } } diff --git a/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubSourceStorageBuilder.java b/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubSourceStorageBuilder.java index e61c9f226ca..ec1731a9c2b 100644 --- a/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubSourceStorageBuilder.java +++ b/wsmaster/che-core-api-factory-github/src/main/java/org/eclipse/che/api/factory/server/github/GithubSourceStorageBuilder.java @@ -19,6 +19,7 @@ import javax.inject.Singleton; import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto; import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.SourceDto; /** * Create {@link ProjectConfigDto} object from objects @@ -34,7 +35,7 @@ public class GithubSourceStorageBuilder { * @param githubUrl an instance of {@link GithubUrl} * @return newly created source storage DTO object */ - public SourceStorageDto build(GithubUrl githubUrl) { + public SourceStorageDto buildWorkspaceConfigSource(GithubUrl githubUrl) { // Create map for source storage dto Map parameters = new HashMap<>(2); parameters.put("branch", githubUrl.getBranch()); @@ -47,4 +48,18 @@ public SourceStorageDto build(GithubUrl githubUrl) { .withType("github") .withParameters(parameters); } + + /** + * Create SourceStorageDto DTO by using data of a github url + * + * @param githubUrl an instance of {@link GithubUrl} + * @return newly created source DTO object + */ + public SourceDto buildDevfileSource(GithubUrl githubUrl) { + // T_O_D_O add keepDir support when Devfile will support it + return newDto(SourceDto.class) + .withLocation(githubUrl.repositoryLocation()) + .withType("github") + .withBranch(githubUrl.getBranch()); + } } diff --git a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java index 0d149ae45e9..4d8e440841c 100644 --- a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java +++ b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java @@ -14,27 +14,29 @@ import static java.util.Collections.singletonMap; import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION; import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME; +import static org.eclipse.che.api.workspace.server.devfile.Constants.CURRENT_API_VERSION; import static org.eclipse.che.dto.server.DtoFactory.newDto; -import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; import org.eclipse.che.api.factory.server.urlfactory.ProjectConfigDtoMerger; import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl; import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder; import org.eclipse.che.api.factory.shared.dto.FactoryDto; import org.eclipse.che.api.workspace.server.devfile.FileContentProvider; -import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto; -import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto; +import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.MetadataDto; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; @@ -65,9 +67,6 @@ public class GithubFactoryParametersResolverTest { /** Parser which will allow to check validity of URLs and create objects. */ @Mock private URLFactoryBuilder urlFactoryBuilder; - /** Capturing the project config DTO supplier parameter. */ - @Captor private ArgumentCaptor> projectConfigDtoArgumentCaptor; - /** * Capturing the location parameter when calling {@link * URLFactoryBuilder#createFactoryFromJson(RemoteFactoryUrl)} or {@link @@ -106,109 +105,60 @@ public void checkValidAcceptUrl() { assertTrue(accept); } - /** Check that with a simple valid URL github url it works */ @Test - public void shouldReturnGitHubSimpleRepoFactory() throws Exception { + public void shouldGenerateDevfileForFactoryWithNoDevfileOrJson() throws Exception { String githubUrl = "https://github.com/eclipse/che"; - FactoryDto computedFactory = newDto(FactoryDto.class).withV(CURRENT_VERSION).withSource("repo"); + FactoryDto computedFactory = generateDevfileFactory(); + + when(urlFactoryBuilder.buildDefaultDevfile(any())).thenReturn(computedFactory.getDevfile()); + when(urlFactoryBuilder.createFactoryFromJson(any(RemoteFactoryUrl.class))) .thenReturn(Optional.empty()); when(urlFactoryBuilder.createFactoryFromDevfile(any(RemoteFactoryUrl.class), any())) .thenReturn(Optional.empty()); - when(projectConfigDtoMerger.merge(any(FactoryDto.class), any())).then(returnsFirstArg()); - FactoryDto factory = githubFactoryParametersResolver.createFactory(singletonMap(URL_PARAMETER_NAME, githubUrl)); - // check we provide dockerfile and correct env - verify(urlFactoryBuilder).buildDefaultWorkspaceConfig(eq("che")); + verify(urlFactoryBuilder).buildDefaultDevfile(eq("che")); assertEquals(factory, computedFactory); } - /** Check that with a simple valid URL github url it works */ @Test - public void shouldReturnGitHubSimpleJsonFactory() throws Exception { + public void shouldReturnFactoryFromRepositoryWithDevfile() throws Exception { String githubUrl = "https://github.com/eclipse/che"; - FactoryDto computedFactory = newDto(FactoryDto.class).withV(CURRENT_VERSION); - when(urlFactoryBuilder.createFactoryFromJson(any(RemoteFactoryUrl.class))) - .thenReturn(Optional.of(computedFactory)); - - githubFactoryParametersResolver.createFactory(singletonMap(URL_PARAMETER_NAME, githubUrl)); - - // check we called the builder with the following factory json file - verify(urlFactoryBuilder).createFactoryFromJson(factoryUrlArgumentCaptor.capture()); - assertEquals( - factoryUrlArgumentCaptor.getValue().factoryFileLocation(), - "https://raw.githubusercontent.com/eclipse/che/master/.factory.json"); - - assertEquals(factoryUrlArgumentCaptor.getValue().getFactoryFilename(), ".factory.json"); - - // check we provide dockerfile and correct env - verify(urlFactoryBuilder).buildDefaultWorkspaceConfig(eq("che")); - - // check project config built - verify(projectConfigDtoMerger) - .merge(any(FactoryDto.class), projectConfigDtoArgumentCaptor.capture()); - - ProjectConfigDto projectConfigDto = projectConfigDtoArgumentCaptor.getValue().get(); - - SourceStorageDto sourceStorageDto = projectConfigDto.getSource(); - assertNotNull(sourceStorageDto); - assertEquals(sourceStorageDto.getType(), "github"); - assertEquals(sourceStorageDto.getLocation(), githubUrl); - Map sourceParameters = sourceStorageDto.getParameters(); - assertEquals(sourceParameters.size(), 1); - assertEquals(sourceParameters.get("branch"), "master"); - } - - /** Check that with a simple valid URL github url it works */ - @Test - public void shouldReturnGitHubDevfileFactory() throws Exception { - - String githubUrl = "https://github.com/eclipse/che"; + FactoryDto computedFactory = generateDevfileFactory(); - FactoryDto computedFactory = newDto(FactoryDto.class).withV(CURRENT_VERSION); when(urlFactoryBuilder.createFactoryFromDevfile(any(RemoteFactoryUrl.class), any())) .thenReturn(Optional.of(computedFactory)); - githubFactoryParametersResolver.createFactory(singletonMap(URL_PARAMETER_NAME, githubUrl)); + FactoryDto factory = + githubFactoryParametersResolver.createFactory(singletonMap(URL_PARAMETER_NAME, githubUrl)); + + assertNotNull(factory.getDevfile()); + assertNull(factory.getWorkspace()); - // check we called the builder with the following devfile + // check we called the builder with the following devfile file verify(urlFactoryBuilder).createFactoryFromDevfile(factoryUrlArgumentCaptor.capture(), any()); + verify(urlFactoryBuilder, never()).buildDefaultDevfile(eq("che")); assertEquals( factoryUrlArgumentCaptor.getValue().devfileFileLocation(), "https://raw.githubusercontent.com/eclipse/che/master/devfile.yaml"); assertEquals(factoryUrlArgumentCaptor.getValue().getDevfileFilename(), "devfile.yaml"); - // check project config built - verify(projectConfigDtoMerger) - .merge(any(FactoryDto.class), projectConfigDtoArgumentCaptor.capture()); - - ProjectConfigDto projectConfigDto = projectConfigDtoArgumentCaptor.getValue().get(); - - SourceStorageDto sourceStorageDto = projectConfigDto.getSource(); - assertNotNull(sourceStorageDto); - assertEquals(sourceStorageDto.getType(), "github"); - assertEquals(sourceStorageDto.getLocation(), githubUrl); - Map sourceParameters = sourceStorageDto.getParameters(); - assertEquals(sourceParameters.size(), 1); - assertEquals(sourceParameters.get("branch"), "master"); } - /** Check that we've expected branch when url contains a branch name */ @Test - public void shouldReturnGitHubBranchFactory() throws Exception { + public void shouldReturnFactoryFromRepositoryWithFactoryJson() throws Exception { + + String githubUrl = "https://github.com/eclipse/che"; - String githubUrl = "https://github.com/eclipse/che/tree/4.2.x"; - String githubCloneUrl = "https://github.com/eclipse/che"; - String githubBranch = "4.2.x"; + FactoryDto computedFactory = generateWsConfigFactory(); - FactoryDto computedFactory = newDto(FactoryDto.class).withV(CURRENT_VERSION); when(urlFactoryBuilder.createFactoryFromJson(any(RemoteFactoryUrl.class))) .thenReturn(Optional.of(computedFactory)); @@ -216,67 +166,28 @@ public void shouldReturnGitHubBranchFactory() throws Exception { // check we called the builder with the following factory json file verify(urlFactoryBuilder).createFactoryFromJson(factoryUrlArgumentCaptor.capture()); + verify(urlFactoryBuilder, never()).buildDefaultDevfile(eq("che")); assertEquals( factoryUrlArgumentCaptor.getValue().factoryFileLocation(), - "https://raw.githubusercontent.com/eclipse/che/4.2.x/.factory.json"); + "https://raw.githubusercontent.com/eclipse/che/master/.factory.json"); assertEquals(factoryUrlArgumentCaptor.getValue().getFactoryFilename(), ".factory.json"); - - // check we provide dockerfile and correct env - verify(urlFactoryBuilder).buildDefaultWorkspaceConfig(eq("che")); - - // check project config built - verify(projectConfigDtoMerger) - .merge(any(FactoryDto.class), projectConfigDtoArgumentCaptor.capture()); - - ProjectConfigDto projectConfigDto = projectConfigDtoArgumentCaptor.getValue().get(); - SourceStorageDto sourceStorageDto = projectConfigDto.getSource(); - assertNotNull(sourceStorageDto); - assertEquals(sourceStorageDto.getType(), "github"); - assertEquals(sourceStorageDto.getLocation(), githubCloneUrl); - Map sourceParameters = sourceStorageDto.getParameters(); - assertEquals(sourceParameters.size(), 1); - assertEquals(sourceParameters.get("branch"), githubBranch); } - /** Check that we have a sparse checkout "keepDir" if url contains branch and subtree. */ - @Test - public void shouldReturnGitHubBranchAndKeepdirFactory() throws Exception { - - String githubUrl = "https://github.com/eclipse/che/tree/4.2.x/dashboard"; - String githubCloneUrl = "https://github.com/eclipse/che"; - String githubBranch = "4.2.x"; - String githubKeepdir = "dashboard"; - - FactoryDto computedFactory = newDto(FactoryDto.class).withV(CURRENT_VERSION); - when(urlFactoryBuilder.createFactoryFromJson(any(RemoteFactoryUrl.class))) - .thenReturn(Optional.of(computedFactory)); - - githubFactoryParametersResolver.createFactory(singletonMap(URL_PARAMETER_NAME, githubUrl)); - - // check we called the builder with the following factory json file - verify(urlFactoryBuilder).createFactoryFromJson(factoryUrlArgumentCaptor.capture()); - assertEquals( - factoryUrlArgumentCaptor.getValue().factoryFileLocation(), - "https://raw.githubusercontent.com/eclipse/che/4.2.x/.factory.json"); - - assertEquals(factoryUrlArgumentCaptor.getValue().getFactoryFilename(), ".factory.json"); + private FactoryDto generateDevfileFactory() { + return newDto(FactoryDto.class) + .withV(CURRENT_VERSION) + .withSource("repo") + .withDevfile( + newDto(DevfileDto.class) + .withApiVersion(CURRENT_API_VERSION) + .withMetadata(newDto(MetadataDto.class).withName("che"))); + } - // check we provide dockerfile and correct env - verify(urlFactoryBuilder).buildDefaultWorkspaceConfig(eq("che")); - - // check project config built - verify(projectConfigDtoMerger) - .merge(any(FactoryDto.class), projectConfigDtoArgumentCaptor.capture()); - - ProjectConfigDto projectConfigDto = projectConfigDtoArgumentCaptor.getValue().get(); - SourceStorageDto sourceStorageDto = projectConfigDto.getSource(); - assertNotNull(sourceStorageDto); - assertEquals(sourceStorageDto.getType(), "github"); - assertEquals(sourceStorageDto.getLocation(), githubCloneUrl); - Map sourceParameters = sourceStorageDto.getParameters(); - assertEquals(sourceParameters.size(), 2); - assertEquals(sourceParameters.get("branch"), githubBranch); - assertEquals(sourceParameters.get("keepDir"), githubKeepdir); + private FactoryDto generateWsConfigFactory() { + return newDto(FactoryDto.class) + .withV(CURRENT_VERSION) + .withSource("repo") + .withWorkspace(newDto(WorkspaceConfigDto.class).withName("che")); } } diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java index 78555da552c..043b1b95dee 100644 --- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java +++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java @@ -20,6 +20,7 @@ import org.eclipse.che.api.core.rest.shared.dto.Hyperlinks; import org.eclipse.che.api.core.rest.shared.dto.Link; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; import org.eclipse.che.dto.shared.DTO; /** @@ -38,8 +39,16 @@ public interface FactoryDto extends Factory, Hyperlinks { FactoryDto withV(String v); + @FactoryParameter(obligation = OPTIONAL) + DevfileDto getDevfile(); + + void setDevfile(DevfileDto workspace); + + FactoryDto withDevfile(DevfileDto devfileDto); + + /** because factory DTO may have devfile, in that case, workspace may be optional */ @Override - @FactoryParameter(obligation = MANDATORY) + @FactoryParameter(obligation = OPTIONAL) WorkspaceConfigDto getWorkspace(); void setWorkspace(WorkspaceConfigDto workspace); diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/ProjectConfigDtoMerger.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/ProjectConfigDtoMerger.java index 15d1580dece..f470fa4adcb 100644 --- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/ProjectConfigDtoMerger.java +++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/ProjectConfigDtoMerger.java @@ -47,6 +47,11 @@ public class ProjectConfigDtoMerger { */ public FactoryDto merge(FactoryDto factory, Supplier configSupplier) { + if (factory.getWorkspace() == null) { + // factory is created with devfile. There is no need to provision projects + return factory; + } + final List projects = factory.getWorkspace().getProjects(); if (projects == null || projects.isEmpty()) { factory.getWorkspace().setProjects(singletonList(configSupplier.get())); diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilder.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilder.java index 1cd93be15a3..afe58ee196f 100644 --- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilder.java +++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilder.java @@ -13,6 +13,7 @@ import static com.google.common.base.Strings.isNullOrEmpty; import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION; +import static org.eclipse.che.api.workspace.server.devfile.Constants.CURRENT_API_VERSION; import static org.eclipse.che.api.workspace.shared.Constants.WORKSPACE_TOOLING_EDITOR_ATTRIBUTE; import static org.eclipse.che.api.workspace.shared.Constants.WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE; import static org.eclipse.che.dto.server.DtoFactory.newDto; @@ -31,9 +32,10 @@ import org.eclipse.che.api.workspace.server.devfile.FileContentProvider; import org.eclipse.che.api.workspace.server.devfile.URLFetcher; import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException; -import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.MetadataDto; import org.eclipse.che.dto.server.DtoFactory; /** @@ -105,12 +107,12 @@ public Optional createFactoryFromDevfile( } try { DevfileImpl devfile = devfileManager.parseYaml(devfileYamlContent); - WorkspaceConfigImpl wsConfig = - devfileManager.createWorkspaceConfig(devfile, fileContentProvider); + devfileManager.resolveReference(devfile, fileContentProvider); + FactoryDto factoryDto = newDto(FactoryDto.class) .withV(CURRENT_VERSION) - .withWorkspace(DtoConverter.asDto(wsConfig)) + .withDevfile(DtoConverter.asDto(devfile)) .withSource(remoteFactoryUrl.getDevfileFilename()); return Optional.of(factoryDto); } catch (DevfileException e) { @@ -137,4 +139,18 @@ public WorkspaceConfigDto buildDefaultWorkspaceConfig(String name) { // workspace configuration using the environment return newDto(WorkspaceConfigDto.class).withName(name).withAttributes(attributes); } + + /** + * Help to generate default workspace devfile. Also initialise project in it + * + * @param name the name of the workspace + * @return a workspace devfile + */ + public DevfileDto buildDefaultDevfile(String name) { + + // workspace configuration using the environment + return newDto(DevfileDto.class) + .withApiVersion(CURRENT_API_VERSION) + .withMetadata(newDto(MetadataDto.class).withName(name)); + } } diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/DefaultFactoryParameterResolverTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/DefaultFactoryParameterResolverTest.java index 71293f52bdf..994a6c27288 100644 --- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/DefaultFactoryParameterResolverTest.java +++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/DefaultFactoryParameterResolverTest.java @@ -16,36 +16,23 @@ import static org.eclipse.che.api.workspace.server.devfile.Constants.KUBERNETES_COMPONENT_TYPE; import static org.eclipse.che.api.workspace.server.devfile.Constants.OPENSHIFT_COMPONENT_TYPE; import static org.eclipse.che.api.workspace.server.devfile.Constants.PLUGIN_COMPONENT_TYPE; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder; import org.eclipse.che.api.workspace.server.WorkspaceManager; import org.eclipse.che.api.workspace.server.devfile.DevfileManager; -import org.eclipse.che.api.workspace.server.devfile.FileContentProvider; import org.eclipse.che.api.workspace.server.devfile.URLFetcher; -import org.eclipse.che.api.workspace.server.devfile.convert.CommandConverter; -import org.eclipse.che.api.workspace.server.devfile.convert.DefaultEditorProvisioner; import org.eclipse.che.api.workspace.server.devfile.convert.DevfileConverter; -import org.eclipse.che.api.workspace.server.devfile.convert.ProjectConverter; -import org.eclipse.che.api.workspace.server.devfile.convert.component.ComponentFQNParser; -import org.eclipse.che.api.workspace.server.devfile.convert.component.ComponentProvisioner; -import org.eclipse.che.api.workspace.server.devfile.convert.component.ComponentToWorkspaceApplier; import org.eclipse.che.api.workspace.server.devfile.schema.DevfileSchemaProvider; import org.eclipse.che.api.workspace.server.devfile.validator.ComponentIntegrityValidator; import org.eclipse.che.api.workspace.server.devfile.validator.ComponentIntegrityValidator.NoopComponentIntegrityValidator; import org.eclipse.che.api.workspace.server.devfile.validator.DevfileIntegrityValidator; import org.eclipse.che.api.workspace.server.devfile.validator.DevfileSchemaValidator; -import org.eclipse.che.api.workspace.server.model.impl.devfile.ComponentImpl; -import org.eclipse.che.api.workspace.server.wsplugins.PluginFQNParser; import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; import org.testng.annotations.Listeners; @@ -65,7 +52,6 @@ public class DefaultFactoryParameterResolverTest { + " reference: ../localfile\n"; @Mock private URLFetcher urlFetcher; - private ComponentFQNParser componentFQNParser = new ComponentFQNParser(new PluginFQNParser()); @Test public void shouldResolveRelativeFiles() throws Exception { @@ -81,32 +67,8 @@ public void shouldResolveRelativeFiles() throws Exception { validators.put(OPENSHIFT_COMPONENT_TYPE, new NoopComponentIntegrityValidator()); DevfileIntegrityValidator integrityValidator = new DevfileIntegrityValidator(validators); - Set componentProvisioners = new HashSet<>(); - Map appliers = new HashMap<>(); - ComponentToWorkspaceApplier applier = mock(ComponentToWorkspaceApplier.class); - appliers.put("kubernetes", applier); - - doAnswer( - i -> { - // in here we mock that the component applier requests the contents of the referenced - // local file. That's all we need to happen - FileContentProvider p = i.getArgument(2); - ComponentImpl component = i.getArgument(1); - p.fetchContent(component.getReference()); - return null; - }) - .when(applier) - .apply(any(), any(), any()); - - DevfileConverter devfileConverter = - new DevfileConverter( - new ProjectConverter(), - new CommandConverter(), - componentProvisioners, - appliers, - new DefaultEditorProvisioner(null, new String[] {}, componentFQNParser), - new URLFetcher()); + DevfileConverter devfileConverter = mock(DevfileConverter.class); WorkspaceManager workspaceManager = mock(WorkspaceManager.class); DevfileManager devfileManager = diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilderTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilderTest.java index 303a245f61f..2b54f5f7694 100644 --- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilderTest.java +++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/urlfactory/URLFactoryBuilderTest.java @@ -14,12 +14,10 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION; -import static org.eclipse.che.api.workspace.server.DtoConverter.asDto; import static org.eclipse.che.api.workspace.server.devfile.Constants.KUBERNETES_COMPONENT_TYPE; import static org.eclipse.che.api.workspace.shared.Constants.WORKSPACE_TOOLING_EDITOR_ATTRIBUTE; import static org.eclipse.che.api.workspace.shared.Constants.WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE; import static org.eclipse.che.dto.server.DtoFactory.newDto; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; @@ -120,8 +118,6 @@ public void checkWithCustomDevfileAndRecipe() throws Exception { when(urlFetcher.fetchSafely(anyString())).thenReturn("random_content"); when(devfileManager.parseYaml(anyString())).thenReturn(devfile); - when(devfileManager.createWorkspaceConfig(any(DevfileImpl.class), any())) - .thenReturn(workspaceConfigImpl); FactoryDto factory = urlFactoryBuilder @@ -132,8 +128,6 @@ public void checkWithCustomDevfileAndRecipe() throws Exception { s -> myLocation + ".list") .get(); - WorkspaceConfigDto expectedWorkspaceConfig = asDto(workspaceConfigImpl); - assertEquals(factory.getWorkspace(), expectedWorkspaceConfig); assertEquals(factory.getSource(), "devfile.yml"); } } diff --git a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/ComponentDto.java b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/ComponentDto.java index 4aed53774e9..982ce99e50f 100644 --- a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/ComponentDto.java +++ b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/ComponentDto.java @@ -98,11 +98,11 @@ public interface ComponentDto extends Component { ComponentDto withMemoryLimit(String memoryLimit); @Override - boolean getMountSources(); + Boolean getMountSources(); - void setMountSources(boolean mountSources); + void setMountSources(Boolean mountSources); - ComponentDto withMountSources(boolean mountSources); + ComponentDto withMountSources(Boolean mountSources); @Override List getCommand(); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DtoConverter.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DtoConverter.java index 14b5aca272d..c88ea92349d 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DtoConverter.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DtoConverter.java @@ -104,7 +104,7 @@ public static WorkspaceDto asDto(Workspace workspace) { return workspaceDto; } - private static DevfileDto asDto(Devfile devfile) { + public static DevfileDto asDto(Devfile devfile) { List commands = devfile.getCommands().stream().map(DtoConverter::asDto).collect(toList()); List components = diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileManager.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileManager.java index d04883556d9..262b11148b6 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileManager.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileManager.java @@ -11,8 +11,13 @@ */ package org.eclipse.che.api.workspace.server.devfile; +import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static java.lang.String.format; import static java.util.Collections.emptyMap; +import static org.eclipse.che.api.workspace.server.devfile.Constants.KUBERNETES_COMPONENT_TYPE; +import static org.eclipse.che.api.workspace.server.devfile.Constants.OPENSHIFT_COMPONENT_TYPE; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -20,6 +25,9 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; import org.eclipse.che.api.core.ConflictException; @@ -35,6 +43,7 @@ import org.eclipse.che.api.workspace.server.devfile.validator.DevfileSchemaValidator; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl; +import org.eclipse.che.api.workspace.server.model.impl.devfile.ComponentImpl; import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; import org.eclipse.che.commons.env.EnvironmentContext; @@ -107,6 +116,37 @@ public DevfileImpl parseJson(String devfileContent) throws DevfileFormatExceptio return parse(devfileContent, schemaValidator::validateJson); } + /** + * Resolve devfile component references into their reference content. + * + * @param devfile input devfile + * @param fileContentProvider provider to fetch reference content + */ + public void resolveReference(DevfileImpl devfile, FileContentProvider fileContentProvider) + throws DevfileException { + List toResolve = + devfile + .getComponents() + .stream() + .filter( + c -> + c.getType().equals(KUBERNETES_COMPONENT_TYPE) + || c.getType().equals(OPENSHIFT_COMPONENT_TYPE)) + .filter(c -> !isNullOrEmpty(c.getReference())) + .collect(Collectors.toList()); + for (ComponentImpl c : toResolve) { + try { + c.setReferenceContent(fileContentProvider.fetchContent(c.getReference())); + } catch (IOException e) { + throw new DevfileException( + format( + "Unable to resolve reference of component: %s", + firstNonNull(c.getAlias(), c.getReference())), + e); + } + } + } + private DevfileImpl parse(String content, ValidationFunction validationFunction) throws DevfileFormatException { JsonNode parsed = validationFunction.validate(content); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileService.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileService.java index 7bddbb1fa1b..d2698f66db1 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileService.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileService.java @@ -26,6 +26,7 @@ import io.swagger.annotations.Example; import io.swagger.annotations.ExampleProperty; import java.io.IOException; +import java.util.List; import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -41,11 +42,13 @@ import org.eclipse.che.api.core.ValidationException; import org.eclipse.che.api.core.rest.Service; import org.eclipse.che.api.workspace.server.WorkspaceLinksGenerator; +import org.eclipse.che.api.workspace.server.WorkspaceService; import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException; import org.eclipse.che.api.workspace.server.devfile.schema.DevfileSchemaProvider; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl; import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; @Api(value = "/devfile", description = "Devfile REST API") @Path("/devfile") @@ -95,6 +98,8 @@ public Response getSchema() throws ServerException { * * @param data devfile content * @return created workspace configuration + * @deprecated This method of workspace creation is deprecated in favor of {@link + * WorkspaceService#create(DevfileDto, List, Boolean, String)} */ @POST @Consumes({"text/yaml", "text/x-yaml", "application/yaml", "application/json"}) @@ -114,6 +119,7 @@ public Response getSchema() throws ServerException { @ApiResponse(code = 403, message = "The user does not have access to create a new workspace"), @ApiResponse(code = 500, message = "Internal server error occurred") }) + @Deprecated public Response createFromYaml(String data) throws ServerException, ConflictException, NotFoundException, ValidationException, BadRequestException { diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ComponentImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ComponentImpl.java index 070f0facbcf..9129cca8070 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ComponentImpl.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ComponentImpl.java @@ -87,7 +87,7 @@ public class ComponentImpl implements Component { private String memoryLimit; @Column(name = "mount_sources") - private boolean mountSources; + private Boolean mountSources; @ElementCollection(fetch = FetchType.EAGER) @CollectionTable( @@ -160,7 +160,7 @@ public ComponentImpl( String alias, String image, String memoryLimit, - boolean mountSources, + Boolean mountSources, List command, List args, List volumes, @@ -198,7 +198,7 @@ public ComponentImpl( List entrypoints, String image, String memoryLimit, - boolean mountSources, + Boolean mountSources, List command, List args, List volumes, @@ -366,11 +366,11 @@ public void setMemoryLimit(String memoryLimit) { } @Override - public boolean getMountSources() { + public Boolean getMountSources() { return mountSources; } - public void setMountSources(boolean mountSources) { + public void setMountSources(Boolean mountSources) { this.mountSources = mountSources; } diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileManagerTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileManagerTest.java index 76393e8d58e..6f3701d847c 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileManagerTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileManagerTest.java @@ -11,6 +11,7 @@ */ package org.eclipse.che.api.workspace.server.devfile; +import static org.eclipse.che.api.workspace.server.devfile.Constants.KUBERNETES_COMPONENT_TYPE; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; @@ -33,6 +34,7 @@ import org.eclipse.che.api.core.model.workspace.WorkspaceStatus; import org.eclipse.che.api.workspace.server.WorkspaceManager; import org.eclipse.che.api.workspace.server.devfile.convert.DevfileConverter; +import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException; import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException; import org.eclipse.che.api.workspace.server.devfile.validator.DevfileIntegrityValidator; import org.eclipse.che.api.workspace.server.devfile.validator.DevfileSchemaValidator; @@ -68,6 +70,7 @@ public class DevfileManagerTest { @Mock private DevfileConverter devfileConverter; @Mock private WorkspaceManager workspaceManager; @Mock private ObjectMapper objectMapper; + @Mock private FileContentProvider contentProvider; @Mock private JsonNode devfileJsonNode; private DevfileImpl devfile; @@ -114,6 +117,44 @@ public void testInitializingDevfileMapsAfterParsing() throws Exception { assertNotNull(parsed.getComponents().get(0).getEndpoints().get(0).getAttributes()); } + @Test + public void shouldResolveReferencesIntoReferenceContentForFactories() throws Exception { + + String referenceContent = "my_content_yaml_v3"; + when(contentProvider.fetchContent(anyString())).thenReturn(referenceContent); + + ComponentImpl component = new ComponentImpl(); + component.setType(KUBERNETES_COMPONENT_TYPE); + component.setReference("myfile.yaml"); + devfile.getComponents().add(component); + + // when + devfileManager.resolveReference(devfile, contentProvider); + + // then + verify(contentProvider).fetchContent(eq("myfile.yaml")); + assertEquals(referenceContent, devfile.getComponents().get(0).getReferenceContent()); + } + + @Test( + expectedExceptions = DevfileException.class, + expectedExceptionsMessageRegExp = "Unable to resolve reference of component: test") + public void shouldThrowDevfileExceptionWhenReferenceIsNotResolvable() throws Exception { + + when(contentProvider.fetchContent(anyString())).thenThrow(IOException.class); + + ComponentImpl component = new ComponentImpl(); + component.setType(KUBERNETES_COMPONENT_TYPE); + component.setAlias("test"); + component.setReference("myfile.yaml"); + devfile.getComponents().add(component); + + // when + devfileManager.resolveReference(devfile, contentProvider); + + // then exception is thrown + } + @Test( expectedExceptions = DevfileFormatException.class, expectedExceptionsMessageRegExp = "non valid")