From 1cc53f05e4c585e03626c053ea87879e520eccf1 Mon Sep 17 00:00:00 2001 From: Alexander Garagatyi Date: Tue, 23 Feb 2016 17:14:56 +0200 Subject: [PATCH] CHE-457: add servers conf and env vars to model of machine config. Signed-off-by: Alexander Garagatyi --- .../org/eclipse/che/api/deploy/ApiModule.java | 5 +- assembly/assembly-machine-war/pom.xml | 3 +- .../api/core/model/machine/MachineConfig.java | 15 + .../model/machine/MachineRuntimeInfo.java | 14 +- .../api/core/model/machine/ServerConf.java | 56 ++ core/ide/che-core-ide-app/pom.xml | 5 + .../create/CreateWorkspacePresenterTest.java | 40 +- .../che/api/account/AccountServiceTest.java | 4 +- .../server/builder/FactoryBuilderTest.java | 12 +- .../che/api/local/LocalWorkspaceDaoTest.java | 13 +- .../che/api/machine/server/DtoConverter.java | 19 +- .../machine/server/WsAgentLauncherImpl.java | 4 +- .../server/model/impl/MachineConfigImpl.java | 149 +++- .../server/model/impl/MachineImpl.java | 11 + .../server/model/impl/MachineSourceImpl.java | 5 + .../server/model/impl/ServerConfImpl.java | 75 ++ .../proxy/MachineExtensionProxyServlet.java | 10 +- .../machine/shared/dto/MachineConfigDto.java | 11 + .../api/machine/shared/dto/ServerConfDto.java | 26 + .../machine/server/MachineManagerTest.java | 25 +- .../server/WsAgentLauncherImplTest.java | 2 +- .../MachineExtensionProxyServletTest.java | 6 +- .../DefaultWorkspaceConfigValidator.java | 83 ++- .../DefaultWorkspaceConfigValidatorTest.java | 186 ++++- .../server/WorkspaceManagerTest.java | 21 +- .../server/stack/StackLoaderTest.java | 18 +- .../server/stack/StackServiceTest.java | 11 +- .../plugin/docker/machine/DockerInstance.java | 5 +- .../machine/DockerInstanceProvider.java | 62 +- .../machine/DockerInstanceRuntimeInfo.java | 118 ++- .../docker/machine/DockerMachineFactory.java | 5 +- .../docker/machine/DockerMachineModule.java | 6 +- .../che/plugin/docker/machine/ServerConf.java | 75 -- .../machine/ext/DockerExtServerModule.java | 2 +- .../machine/ext/DockerTerminalModule.java | 2 +- .../provider/TerminalServerConfProvider.java | 5 +- .../provider/WsAgentServerConfProvider.java | 8 +- .../local/LocalDockerInstanceRuntimeInfo.java | 20 +- .../machine/DockerInstanceProviderTest.java | 693 ++++++++++-------- .../DockerInstanceReadFileContentTest.java | 20 +- .../DockerInstanceRuntimeInfoTest.java | 471 ++++++++++++ .../remotedebug/RemoteDebugPresenter.java | 10 +- .../valueproviders/ServerPortProvider.java | 11 +- .../processes/ConsolesPanelPresenter.java | 4 +- .../client/processes/ProcessTreeRenderer.java | 2 +- 45 files changed, 1746 insertions(+), 602 deletions(-) create mode 100644 core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/ServerConf.java create mode 100644 core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/ServerConfImpl.java create mode 100644 core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/ServerConfDto.java delete mode 100644 plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ServerConf.java create mode 100644 plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfoTest.java diff --git a/assembly/assembly-ide-war/src/main/java/org/eclipse/che/api/deploy/ApiModule.java b/assembly/assembly-ide-war/src/main/java/org/eclipse/che/api/deploy/ApiModule.java index 089c7d844d1..8d2209869b4 100644 --- a/assembly/assembly-ide-war/src/main/java/org/eclipse/che/api/deploy/ApiModule.java +++ b/assembly/assembly-ide-war/src/main/java/org/eclipse/che/api/deploy/ApiModule.java @@ -15,11 +15,13 @@ import com.google.inject.name.Names; import org.eclipse.che.api.auth.AuthenticationService; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.api.core.notification.WSocketEventBusServer; import org.eclipse.che.api.core.rest.ApiInfoService; import org.eclipse.che.api.core.rest.CoreRestModule; import org.eclipse.che.api.local.LocalInfrastructureModule; import org.eclipse.che.api.machine.server.MachineModule; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.api.machine.server.recipe.PermissionsChecker; import org.eclipse.che.api.machine.server.recipe.PermissionsCheckerImpl; import org.eclipse.che.api.machine.server.recipe.RecipeLoader; @@ -38,7 +40,6 @@ import org.eclipse.che.everrest.ETagResponseFilter; import org.eclipse.che.everrest.EverrestDownloadFileResponseFilter; import org.eclipse.che.inject.DynaModule; -import org.eclipse.che.plugin.docker.machine.ServerConf; import org.eclipse.che.plugin.docker.machine.ext.DockerExtServerModule; import org.eclipse.che.plugin.docker.machine.ext.DockerMachineExtServerChecker; import org.eclipse.che.plugin.docker.machine.ext.DockerMachineTerminalChecker; @@ -112,7 +113,7 @@ protected void configure() { Multibinder machineServers = Multibinder.newSetBinder(binder(), ServerConf.class, Names.named("machine.docker.dev_machine.machine_servers")); - machineServers.addBinding().toInstance(new ServerConf("extensions-debug", "4403", "http")); + machineServers.addBinding().toInstance(new ServerConfImpl("extensions-debug", "4403/tcp", "http")); bind(RecipeLoader.class); Multibinder.newSetBinder(binder(), String.class, Names.named("predefined.recipe.path")) diff --git a/assembly/assembly-machine-war/pom.xml b/assembly/assembly-machine-war/pom.xml index ed8ad2ea0a6..0a90f6a260e 100644 --- a/assembly/assembly-machine-war/pom.xml +++ b/assembly/assembly-machine-war/pom.xml @@ -175,8 +175,7 @@ WEB-INF/lib/*gwt*.jar, WEB-INF/lib/gin-*.jar, - WEB-INF/lib/che-core-api-analytics-*.jar - + WEB-INF/lib/che-core-api-analytics-*.jar diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineConfig.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineConfig.java index e515786617e..e2dde52d2f3 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineConfig.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineConfig.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.eclipse.che.api.core.model.machine; +import java.util.List; +import java.util.Map; + /** * @author gazarenkov */ @@ -39,4 +42,16 @@ public interface MachineConfig { * Machine limits such as RAM size. */ Limits getLimits(); + + /** + * Get configuration of servers inside of machine. + * + *

Key is port/transport protocol, e.g. 8080/tcp or 100100/udp + */ + List getServers(); + + /** + * Get predefined environment variables of machine. + */ + Map getEnvVariables(); } diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineRuntimeInfo.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineRuntimeInfo.java index 0b65bd7dbf3..44b2f0b419c 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineRuntimeInfo.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/MachineRuntimeInfo.java @@ -34,7 +34,19 @@ public interface MachineRuntimeInfo { String projectsRoot(); /** - * Returns mapping of exposed ports to {@link Server} + * Returns mapping of exposed ports to {@link Server}. + * + *

Key consist of port number and transport protocol - tcp or udp with slash between these parts. + *
Example: + *

+     * {
+     *     8080/tcp : {
+     *         "ref" : "server_reference",
+     *         "address" : "server-with-machines.com",
+     *         "url" : "http://server-with-machines.com:8080"
+     *     }
+     * }
+     * 
*/ Map getServers(); } diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/ServerConf.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/ServerConf.java new file mode 100644 index 00000000000..1a20a35888f --- /dev/null +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/ServerConf.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.api.core.model.machine; + +import org.eclipse.che.commons.annotation.Nullable; + +/** + * Configuration of server that can be started inside of machine + * + * @author Alexander Garagatyi + */ +public interface ServerConf { + /** + * Reference to this server. + */ + @Nullable + String getRef(); + + /** + * Port used by server. + *

+ * If udp transport protocol is used then port should include /udp.
+ * If tcp is used /tcp is not required.
+ * Example: + *

    + *
  • 8080
  • + *
  • 8080/tcp
  • + *
  • 8080/udp
  • + *
+ */ + String getPort(); + + /** + * Protocol for configuring preview url of this server. + *

+ * Example: + *

    + *
  • http
  • + *
  • https
  • + *
  • tcp
  • + *
  • udp
  • + *
  • ws
  • + *
  • wss
  • + *
+ */ + @Nullable + String getProtocol(); +} diff --git a/core/ide/che-core-ide-app/pom.xml b/core/ide/che-core-ide-app/pom.xml index 2835a459366..53329cd41b9 100644 --- a/core/ide/che-core-ide-app/pom.xml +++ b/core/ide/che-core-ide-app/pom.xml @@ -207,6 +207,11 @@ fest-assert test + + org.eclipse.che.core + che-core-commons-test + test + org.hamcrest hamcrest-core diff --git a/core/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/workspace/create/CreateWorkspacePresenterTest.java b/core/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/workspace/create/CreateWorkspacePresenterTest.java index 74042ed0b5b..44afa154597 100644 --- a/core/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/workspace/create/CreateWorkspacePresenterTest.java +++ b/core/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/workspace/create/CreateWorkspacePresenterTest.java @@ -27,6 +27,7 @@ import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto; import org.eclipse.che.api.workspace.shared.dto.UsersWorkspaceDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; +import org.eclipse.che.commons.test.SelfReturningAnswer; import org.eclipse.che.ide.CoreLocalizationConstant; import org.eclipse.che.ide.workspace.DefaultWorkspaceComponent; import org.eclipse.che.ide.workspace.WorkspaceComponent; @@ -45,9 +46,8 @@ import org.mockito.runners.MockitoJUnitRunner; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; -import java.util.Map; import static org.eclipse.che.ide.workspace.create.CreateWorkspacePresenter.MAX_COUNT; import static org.eclipse.che.ide.workspace.create.CreateWorkspacePresenter.RECIPE_TYPE; @@ -100,8 +100,8 @@ public class CreateWorkspacePresenterTest { private LimitsDto limitsDto; //DTOs - @Mock private MachineConfigDto machineConfigDto; + private WorkspaceConfigDto workspaceConfigDto; @Mock private MachineDto machineDto; @Mock @@ -111,8 +111,6 @@ public class CreateWorkspacePresenterTest { @Mock private CommandDto commandDto; @Mock - private WorkspaceConfigDto workspaceConfigDto; - @Mock private UsersWorkspaceDto usersWorkspaceDto; @Captor @@ -127,6 +125,10 @@ public class CreateWorkspacePresenterTest { @Before public void setUp() { + machineConfigDto = mock(MachineConfigDto.class, new SelfReturningAnswer()); + workspaceConfigDto = mock(WorkspaceConfigDto.class, new SelfReturningAnswer()); + when(usersWorkspaceDto.getConfig()).thenReturn(workspaceConfigDto); + when(dtoFactory.createDto(MachineSourceDto.class)).thenReturn(machineSourceDto); when(machineSourceDto.withType(anyString())).thenReturn(machineSourceDto); when(machineSourceDto.withLocation(anyString())).thenReturn(machineSourceDto); @@ -135,28 +137,14 @@ public void setUp() { when(limitsDto.withRam(anyInt())).thenReturn(limitsDto); when(dtoFactory.createDto(MachineConfigDto.class)).thenReturn(machineConfigDto); - when(machineConfigDto.withName(anyString())).thenReturn(machineConfigDto); - when(machineConfigDto.withType(anyString())).thenReturn(machineConfigDto); - when(machineConfigDto.withSource(machineSourceDto)).thenReturn(machineConfigDto); - when(machineConfigDto.withDev(anyBoolean())).thenReturn(machineConfigDto); - when(machineConfigDto.withLimits(limitsDto)).thenReturn(machineConfigDto); when(dtoFactory.createDto(EnvironmentDto.class)).thenReturn(environmentDto); when(environmentDto.withName(anyString())).thenReturn(environmentDto); when(environmentDto.withMachineConfigs(Matchers.>anyObject())).thenReturn(environmentDto); when(dtoFactory.createDto(WorkspaceConfigDto.class)).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withName(anyString())).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withDefaultEnv(anyString())).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withEnvironments(Matchers.>anyObject())).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withCommands(Matchers.>anyObject())).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withAttributes(Matchers.>anyObject())).thenReturn(workspaceConfigDto); when(dtoFactory.createDto(UsersWorkspaceDto.class)).thenReturn(usersWorkspaceDto); - when(usersWorkspaceDto.getConfig()).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withName(anyString())).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withDefaultEnv(anyString())).thenReturn(workspaceConfigDto); - when(workspaceConfigDto.withEnvironments(Matchers.>anyObject())).thenReturn(workspaceConfigDto); when(wsComponentProvider.get()).thenReturn(workspaceComponent); @@ -172,7 +160,7 @@ public void delegateShouldBeSet() { @Test public void dialogShouldBeShown() { - presenter.show(Arrays.asList(usersWorkspaceDto), componentCallback); + presenter.show(Collections.singletonList(usersWorkspaceDto), componentCallback); verify(browserQueryFieldRenderer).getWorkspaceName(); verify(view).setWorkspaceName(anyString()); @@ -206,7 +194,7 @@ public void errorLabelShouldBeShownWhenWorkspaceNameIsInCorrect() { public void errorLabelShouldBeShownWhenWorkspaceNameAlreadyExist() { when(workspaceConfigDto.getName()).thenReturn("test"); - presenter.show(Arrays.asList(usersWorkspaceDto), componentCallback); + presenter.show(Collections.singletonList(usersWorkspaceDto), componentCallback); reset(locale); presenter.onNameChanged(); @@ -251,7 +239,7 @@ public void errorLabelShouldBeShownWhenRecipeUrlIsNotCorrect() { @Test public void recipesShouldBeFoundAndShown() throws Exception { - List recipes = Arrays.asList(recipeDescriptor); + List recipes = Collections.singletonList(recipeDescriptor); callSearchRecipesApplyMethod(recipes); @@ -261,7 +249,7 @@ public void recipesShouldBeFoundAndShown() throws Exception { } private void callSearchRecipesApplyMethod(List recipes) throws Exception { - List tags = Arrays.asList("test1 test2"); + List tags = Collections.singletonList("test1 test2"); when(view.getTags()).thenReturn(tags); when(recipeServiceClient.searchRecipes(Matchers.>anyObject(), @@ -309,7 +297,7 @@ private void clickOnCreateButton() { when(userWsPromise.catchError(Matchers.>anyObject())).thenReturn(userWsPromise); when(recipeServiceClient.getRecipes(anyInt(), anyInt())).thenReturn(recipesPromise); - presenter.show(Arrays.asList(usersWorkspaceDto), componentCallback); + presenter.show(Collections.singletonList(usersWorkspaceDto), componentCallback); presenter.onCreateButtonClicked(); @@ -359,7 +347,7 @@ private void callApplyCreateWorkspaceMethod() throws Exception { when(workspaceConfigDto.getDefaultEnv()).thenReturn("name"); when(workspaceConfigDto.getEnvironments()).thenReturn(environments); - when(environmentDto.getMachineConfigs()).thenReturn(Arrays.asList(machineConfigDto)); + when(environmentDto.getMachineConfigs()).thenReturn(Collections.singletonList(machineConfigDto)); clickOnCreateButton(); @@ -389,4 +377,4 @@ public void errorShouldBeCaughtWhenCreatesWorkSpace() throws Exception { verify(promiseError).getCause(); verify(componentCallback).onFailure(Matchers.anyObject()); } -} \ No newline at end of file +} diff --git a/core/platform-api/che-core-api-account/src/test/java/org/eclipse/che/api/account/AccountServiceTest.java b/core/platform-api/che-core-api-account/src/test/java/org/eclipse/che/api/account/AccountServiceTest.java index c97e6af793a..803037479f1 100644 --- a/core/platform-api/che-core-api-account/src/test/java/org/eclipse/che/api/account/AccountServiceTest.java +++ b/core/platform-api/che-core-api-account/src/test/java/org/eclipse/che/api/account/AccountServiceTest.java @@ -594,6 +594,8 @@ private UsersWorkspaceImpl createUsersWorkspace() { "type", new MachineSourceImpl("type", "location"), + null, + null, null))); return new UsersWorkspaceImpl(new WorkspaceConfigImpl("name", "desc", @@ -604,4 +606,4 @@ private UsersWorkspaceImpl createUsersWorkspace() { null) , "id123", "owner1234"); } -} \ No newline at end of file +} diff --git a/core/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/builder/FactoryBuilderTest.java b/core/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/builder/FactoryBuilderTest.java index f5eaca11307..d1f89ebe6f4 100644 --- a/core/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/builder/FactoryBuilderTest.java +++ b/core/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/builder/FactoryBuilderTest.java @@ -28,6 +28,7 @@ import org.eclipse.che.api.machine.shared.dto.CommandDto; import org.eclipse.che.api.machine.shared.dto.MachineConfigDto; import org.eclipse.che.api.machine.shared.dto.MachineSourceDto; +import org.eclipse.che.api.machine.shared.dto.ServerConfDto; import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto; import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto; import org.eclipse.che.api.workspace.shared.dto.RecipeDto; @@ -49,6 +50,7 @@ import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; +import static org.eclipse.che.dto.server.DtoFactory.newDto; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.verify; @@ -176,7 +178,15 @@ private static Factory prepareFactory() { .withType( "git") .withLocation( - "https://github.com/123/test.git")))) + "https://github.com/123/test.git")) + .withServers(Arrays.asList(newDto(ServerConfDto.class).withRef("ref1") + .withPort("8080") + .withProtocol("https"), + newDto(ServerConfDto.class).withRef("ref2") + .withPort("9090/udp") + .withProtocol("someprotocol"))) + .withEnvVariables(Collections.singletonMap("key1", "value1")) + )) .withRecipe(dto.createDto( RecipeDto.class) .withType("sometype") diff --git a/core/platform-api/che-core-api-infrastructure-local/src/test/java/org/eclipse/che/api/local/LocalWorkspaceDaoTest.java b/core/platform-api/che-core-api-infrastructure-local/src/test/java/org/eclipse/che/api/local/LocalWorkspaceDaoTest.java index 3f6a1278926..424d65e10a8 100644 --- a/core/platform-api/che-core-api-infrastructure-local/src/test/java/org/eclipse/che/api/local/LocalWorkspaceDaoTest.java +++ b/core/platform-api/che-core-api-infrastructure-local/src/test/java/org/eclipse/che/api/local/LocalWorkspaceDaoTest.java @@ -18,6 +18,7 @@ import org.eclipse.che.api.machine.server.model.impl.LimitsImpl; import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl; import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.api.machine.server.recipe.RecipeImpl; import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl; import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl; @@ -31,6 +32,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -96,12 +99,18 @@ private static UsersWorkspaceImpl createWorkspace() { "dev-machine", "machine-type", machineSource, - new LimitsImpl(512)); + new LimitsImpl(512), + Arrays.asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")); final MachineConfigImpl machineCfg2 = new MachineConfigImpl(false, "non-dev-machine", "machine-type-2", machineSource, - new LimitsImpl(2048)); + new LimitsImpl(2048), + Arrays.asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")); final EnvironmentImpl env1 = new EnvironmentImpl("my-environment", recipe, asList(machineCfg1, machineCfg2)); final EnvironmentImpl env2 = new EnvironmentImpl("my-environment-2", recipe, singletonList(machineCfg1)); diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/DtoConverter.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/DtoConverter.java index 61e997cdfc1..2f68da30830 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/DtoConverter.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/DtoConverter.java @@ -17,6 +17,7 @@ import org.eclipse.che.api.core.model.machine.MachineRuntimeInfo; import org.eclipse.che.api.core.model.machine.MachineSource; import org.eclipse.che.api.core.model.machine.Server; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.api.core.model.machine.Snapshot; import org.eclipse.che.api.machine.shared.dto.LimitsDto; import org.eclipse.che.api.machine.shared.dto.MachineConfigDto; @@ -24,10 +25,12 @@ import org.eclipse.che.api.machine.shared.dto.MachineProcessDto; import org.eclipse.che.api.machine.shared.dto.MachineRuntimeInfoDto; import org.eclipse.che.api.machine.shared.dto.MachineSourceDto; +import org.eclipse.che.api.machine.shared.dto.ServerConfDto; import org.eclipse.che.api.machine.shared.dto.ServerDto; import org.eclipse.che.api.machine.shared.dto.SnapshotDto; import java.util.Map; +import java.util.stream.Collectors; import static java.util.stream.Collectors.toMap; import static org.eclipse.che.dto.server.DtoFactory.newDto; @@ -48,7 +51,12 @@ public static MachineConfigDto asDto(MachineConfig config) { .withType(config.getType()) .withDev(config.isDev()) .withLimits(asDto(config.getLimits())) - .withSource(asDto(config.getSource())); + .withSource(asDto(config.getSource())) + .withServers(config.getServers() + .stream() + .map(DtoConverter::asDto) + .collect(Collectors.toList())) + .withEnvVariables(config.getEnvVariables()); } /** @@ -104,6 +112,15 @@ public static ServerDto asDto(Server server) { .withUrl(server.getUrl()); } + /** + * Converts {@link ServerConf} to {@link ServerConfDto}. + */ + public static ServerConfDto asDto(ServerConf serverConf) { + return newDto(ServerConfDto.class).withRef(serverConf.getRef()) + .withPort(serverConf.getPort()) + .withProtocol(serverConf.getProtocol()); + } + /** * Converts {@link Snapshot} to {@link SnapshotDto}. */ diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/WsAgentLauncherImpl.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/WsAgentLauncherImpl.java index fc028ebc02c..61e35ddf366 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/WsAgentLauncherImpl.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/WsAgentLauncherImpl.java @@ -40,7 +40,7 @@ public class WsAgentLauncherImpl implements WsAgentLauncher { public static final String WS_AGENT_PROCESS_START_COMMAND = "machine.ws_agent.run_command"; public static final String WS_AGENT_PROCESS_NAME = "CheWsAgent"; - public static final int WS_AGENT_PORT = 4401; + public static final String WS_AGENT_PORT = "4401/tcp"; private static final Logger LOG = LoggerFactory.getLogger(WsAgentLauncherImpl.class); private static final String WS_AGENT_PROCESS_OUTPUT_CHANNEL = "workspace:%s:ext-server:output"; @@ -110,7 +110,7 @@ public void startWsAgent(String workspaceId) throws NotFoundException, MachineEx private HttpJsonRequest createPingRequest(Machine devMachine) { final String wsAgentPingUrl = UriBuilder.fromUri(devMachine.getRuntime() .getServers() - .get(Integer.toString(WS_AGENT_PORT)) + .get(WS_AGENT_PORT) .getUrl()) .replacePath(wsAgentPingPath) .build() diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineConfigImpl.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineConfigImpl.java index dedce6d536e..d35d440e218 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineConfigImpl.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineConfigImpl.java @@ -13,10 +13,14 @@ import org.eclipse.che.api.core.model.machine.Limits; import org.eclipse.che.api.core.model.machine.MachineConfig; import org.eclipse.che.api.core.model.machine.MachineSource; +import org.eclipse.che.api.core.model.machine.ServerConf; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Objects; - -//TODO move? +import java.util.stream.Collectors; /** * Data object for {@link MachineConfig}. @@ -25,11 +29,17 @@ */ public class MachineConfigImpl implements MachineConfig { - private boolean isDev; - private String name; - private String type; - private MachineSourceImpl source; - private LimitsImpl limits; + public static MachineConfigImplBuilder builder() { + return new MachineConfigImplBuilder(); + } + + private boolean isDev; + private String name; + private String type; + private MachineSourceImpl source; + private LimitsImpl limits; + private List servers; + private Map envVariables; public MachineConfigImpl() { } @@ -38,14 +48,23 @@ public MachineConfigImpl(boolean isDev, String name, String type, MachineSource source, - Limits limits) { + Limits limits, + List servers, + Map envVariables) { this.isDev = isDev; this.name = name; this.type = type; + this.envVariables = envVariables; + if (servers != null) { + this.servers = servers.stream() + .map(ServerConfImpl::new) + .collect(Collectors.toList()); + } if (source != null) { - this.source = new MachineSourceImpl(source.getType(), source.getLocation()); + this.source = new MachineSourceImpl(source); } this.limits = new LimitsImpl(limits); + } public MachineConfigImpl(MachineConfig machineCfg) { @@ -53,7 +72,9 @@ public MachineConfigImpl(MachineConfig machineCfg) { machineCfg.getName(), machineCfg.getType(), machineCfg.getSource(), - machineCfg.getLimits()); + machineCfg.getLimits(), + machineCfg.getServers(), + machineCfg.getEnvVariables()); } @Override @@ -61,28 +82,16 @@ public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - @Override public MachineSource getSource() { return source; } - public void setSource(MachineSourceImpl source) { - this.source = source; - } - @Override public boolean isDev() { return isDev; } - public void setDev(boolean isDev) { - this.isDev = isDev; - } - @Override public String getType() { return type; @@ -93,12 +102,24 @@ public Limits getLimits() { return limits; } - public void setLimits(Limits limits) { - this.limits = new LimitsImpl(limits); + @Override + public List getServers() { + if (servers == null) { + servers = new ArrayList<>(); + } + return servers; } - public void setType(String type) { - this.type = type; + @Override + public Map getEnvVariables() { + if (envVariables == null) { + envVariables = new HashMap<>(); + } + return envVariables; + } + + public void setLimits(Limits limits) { + this.limits = new LimitsImpl(limits); } @Override @@ -110,7 +131,9 @@ public boolean equals(Object obj) { Objects.equals(name, other.name) && Objects.equals(source, other.source) && Objects.equals(limits, other.limits) && - Objects.equals(type, other.type); + Objects.equals(type, other.type) && + Objects.equals(getServers(), other.getServers()) && + Objects.equals(getEnvVariables(), other.getEnvVariables()); } @Override @@ -121,6 +144,8 @@ public int hashCode() { hash = hash * 31 + Objects.hashCode(type); hash = hash * 31 + Objects.hashCode(source); hash = hash * 31 + Objects.hashCode(limits); + hash = hash * 31 + Objects.hashCode(getServers()); + hash = hash * 31 + Objects.hashCode(getEnvVariables()); return hash; } @@ -131,7 +156,75 @@ public String toString() { ", name='" + name + '\'' + ", type='" + type + '\'' + ", source=" + source + - ", memorySize=" + limits + + ", limits=" + limits + + ", servers=" + getServers() + + ", envVariables=" + getEnvVariables() + '}'; } + + /** + * Helps to build complex {@link MachineConfigImpl machine config impl}. + * + * @see MachineConfigImpl#builder() + */ + public static class MachineConfigImplBuilder { + + private boolean isDev; + private String name; + private String type; + private MachineSource source; + private Limits limits; + private List servers; + private Map envVariables; + + public MachineConfigImpl build() { + return new MachineConfigImpl(isDev, name, type, source, limits, servers, envVariables); + } + + public MachineConfigImplBuilder fromConfig(MachineConfig machineConfig) { + isDev = machineConfig.isDev(); + name = machineConfig.getName(); + type = machineConfig.getType(); + source = machineConfig.getSource(); + limits = machineConfig.getLimits(); + servers = machineConfig.getServers(); + envVariables = machineConfig.getEnvVariables(); + return this; + } + + public MachineConfigImplBuilder setDev(boolean isDev) { + this.isDev = isDev; + return this; + } + + public MachineConfigImplBuilder setName(String name) { + this.name = name; + return this; + } + + public MachineConfigImplBuilder setType(String type) { + this.type = type; + return this; + } + + public MachineConfigImplBuilder setSource(MachineSource machineSource) { + this.source = machineSource; + return this; + } + + public MachineConfigImplBuilder setLimits(Limits limits) { + this.limits = limits; + return this; + } + + public MachineConfigImplBuilder setServers(List servers) { + this.servers = servers; + return this; + } + + public MachineConfigImplBuilder setEnvVariables(Map envVariables) { + this.envVariables = envVariables; + return this; + } + } } diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineImpl.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineImpl.java index 238fb553301..4dbf3258c26 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineImpl.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineImpl.java @@ -147,6 +147,17 @@ public MachineImpl build() { machineRuntime); } + public MachineImplBuilder fromMachine(Machine machine) { + this.envName = machine.getEnvName(); + this.id = machine.getId(); + this.machineConfig = machine.getConfig(); + this.machineRuntime = machine.getRuntime(); + this.machineStatus = machine.getStatus(); + this.owner = machine.getOwner(); + this.workspaceId = machine.getWorkspaceId(); + return this; + } + public MachineImplBuilder setConfig(MachineConfig machineConfig) { this.machineConfig = machineConfig; return this; diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineSourceImpl.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineSourceImpl.java index 5a3aead53a8..0e814a2e2ff 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineSourceImpl.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/MachineSourceImpl.java @@ -31,6 +31,11 @@ public MachineSourceImpl(String type, String location) { this.location = location; } + public MachineSourceImpl(MachineSource machineSource) { + this.type = machineSource.getType(); + this.location = machineSource.getLocation(); + } + @Override public String getType() { return type; diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/ServerConfImpl.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/ServerConfImpl.java new file mode 100644 index 00000000000..a290dff6250 --- /dev/null +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/model/impl/ServerConfImpl.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.api.machine.server.model.impl; + +import org.eclipse.che.api.core.model.machine.ServerConf; + +import java.util.Objects; + +/** + * @author Alexander Garagatyi + */ +public class ServerConfImpl implements ServerConf { + private final String ref; + private final String port; + private final String protocol; + + public ServerConfImpl(String ref, String port, String protocol) { + this.ref = ref; + this.port = port; + this.protocol = protocol; + } + + public ServerConfImpl(ServerConf serverConf) { + this.ref = serverConf.getRef(); + this.port = serverConf.getPort(); + this.protocol = serverConf.getProtocol(); + } + + @Override + public String getRef() { + return ref; + } + + @Override + public String getPort() { + return port; + } + + @Override + public String getProtocol() { + return protocol; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ServerConfImpl)) return false; + ServerConfImpl that = (ServerConfImpl)o; + return Objects.equals(ref, that.ref) && + Objects.equals(port, that.port) && + Objects.equals(protocol, that.protocol); + } + + @Override + public int hashCode() { + return Objects.hash(ref, port, protocol); + } + + @Override + public String toString() { + return "ServerConfImpl{" + + "ref='" + ref + '\'' + + ", port='" + port + '\'' + + ", protocol='" + protocol + '\'' + + '}'; + } +} diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServlet.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServlet.java index 4d1ca345226..4f525eafc91 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServlet.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServlet.java @@ -50,12 +50,12 @@ public class MachineExtensionProxyServlet extends HttpServlet { private static final String WORKSPACE_ID_PATTERN = "([^/]+)"; private static final Pattern EXTENSION_API_URI = Pattern.compile(".*?/ext/([^/]+/" + WORKSPACE_ID_PATTERN + "/?.*|" + WORKSPACE_ID_PATTERN + "/)"); - private final int extServicesPort; + private final String wsAgentPort; private final MachineManager machineManager; @Inject - public MachineExtensionProxyServlet(@Named("machine.extension.api_port") int extServicesPort, MachineManager machineManager) { - this.extServicesPort = extServicesPort; + public MachineExtensionProxyServlet(@Named("machine.extension.api_port") String wsAgentPort, MachineManager machineManager) { + this.wsAgentPort = wsAgentPort; this.machineManager = machineManager; } @@ -126,7 +126,7 @@ private String getExtensionApiUrl(HttpServletRequest req) throws NotFoundExcepti } final Machine machine = machineManager.getDevMachine(workspaceId); - final Server server = machine.getRuntime().getServers().get(Integer.toString(extServicesPort)); + final Server server = machine.getRuntime().getServers().get(wsAgentPort); if (server == null) { throw new ServerException("No extension server found in machine."); } @@ -139,7 +139,7 @@ private String getExtensionApiUrl(HttpServletRequest req) throws NotFoundExcepti //if not we need to cut wsId from URL if (matcher.group(2) == null) { // here we cut workspaceId from extension API Url for getting access to org.eclipse.che.api.core.rest.ApiInfoService - // e.g localhost:8080/ide/ext/{wsid} -> localhost:{extServicesPort}/ide/ext/ + // e.g localhost:8080/ide/ext/{wsid} -> localhost:{wsAgentPort}/ide/ext/ String originUri = req.getRequestURI(); final int indexOf = originUri.lastIndexOf('/', originUri.length() - 2); uriBuilder.replacePath(originUri.substring(0, indexOf + 1)); diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/MachineConfigDto.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/MachineConfigDto.java index fa28f1a7bd4..eca1ffe8cd8 100644 --- a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/MachineConfigDto.java +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/MachineConfigDto.java @@ -17,6 +17,7 @@ import org.eclipse.che.dto.shared.DTO; import java.util.List; +import java.util.Map; import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.MANDATORY; import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL; @@ -66,6 +67,16 @@ public interface MachineConfigDto extends MachineConfig, Hyperlinks { MachineConfigDto withLimits(LimitsDto limits); + @Override + List getServers(); + + MachineConfigDto withServers(List servers); + + @Override + Map getEnvVariables(); + + MachineConfigDto withEnvVariables(Map envVariables); + @Override MachineConfigDto withLinks(List links); } diff --git a/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/ServerConfDto.java b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/ServerConfDto.java new file mode 100644 index 00000000000..8479cd3369a --- /dev/null +++ b/core/platform-api/che-core-api-machine/src/main/java/org/eclipse/che/api/machine/shared/dto/ServerConfDto.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.api.machine.shared.dto; + +import org.eclipse.che.api.core.model.machine.ServerConf; +import org.eclipse.che.dto.shared.DTO; + +/** + * @author Alexander Garagatyi + */ +@DTO +public interface ServerConfDto extends ServerConf { + ServerConfDto withRef(String ref); + + ServerConfDto withPort(String port); + + ServerConfDto withProtocol(String protocol); +} diff --git a/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/MachineManagerTest.java b/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/MachineManagerTest.java index 38a4dc88a77..2317c356a28 100644 --- a/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/MachineManagerTest.java +++ b/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/MachineManagerTest.java @@ -22,6 +22,7 @@ import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl; import org.eclipse.che.api.machine.server.model.impl.MachineImpl; import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.api.machine.server.recipe.RecipeImpl; import org.eclipse.che.api.machine.server.spi.Instance; import org.eclipse.che.api.machine.server.spi.InstanceProvider; @@ -39,6 +40,8 @@ import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; @@ -122,7 +125,10 @@ public void shouldThrowExceptionOnMachineCreationIfMachineNameIsInvalid() throws "@name!", "machineType", new MachineSourceImpl("Recipe", "location"), - new LimitsImpl(1024)); + new LimitsImpl(1024), + Arrays.asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")); String workspaceId = "wsId"; String environmentName = "env1"; @@ -132,8 +138,10 @@ public void shouldThrowExceptionOnMachineCreationIfMachineNameIsInvalid() throws @Test public void shouldBeAbleToCreateMachineWithValidName() throws Exception { String expectedName = "validMachineName"; - final MachineConfigImpl machineConfig = createMachineConfig(); - machineConfig.setName(expectedName); + final MachineConfigImpl machineConfig = MachineConfigImpl.builder() + .fromConfig(createMachineConfig()) + .setName(expectedName) + .build(); MachineImpl expectedMachine = new MachineImpl(machineConfig, MACHINE_ID, WS_ID, @@ -149,8 +157,10 @@ public void shouldBeAbleToCreateMachineWithValidName() throws Exception { @Test public void shouldCallWsAgentLauncherAfterDevMachineStart() throws Exception { - final MachineConfigImpl machineConfig = createMachineConfig(); - machineConfig.setDev(true); + final MachineConfigImpl machineConfig = MachineConfigImpl.builder() + .fromConfig(createMachineConfig()) + .setDev(true) + .build(); manager.createMachineSync(machineConfig, WS_ID, ENVIRONMENT_NAME); @@ -177,6 +187,9 @@ private MachineConfigImpl createMachineConfig() { "MachineName", "docker", new MachineSourceImpl("Recipe", "location"), - new LimitsImpl(1024)); + new LimitsImpl(1024), + Arrays.asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")); } } diff --git a/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/WsAgentLauncherImplTest.java b/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/WsAgentLauncherImplTest.java index ce47e79e096..a0a9fdca167 100644 --- a/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/WsAgentLauncherImplTest.java +++ b/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/WsAgentLauncherImplTest.java @@ -51,7 +51,7 @@ public class WsAgentLauncherImplTest { private static final String MACHINE_ID = "machineId"; private static final String WS_AGENT_START_CMD_LINE = "cmdLine"; private static final String WS_AGENT_API_ENDPOINT_PATH = "/some/path/"; - private static final String WS_AGENT_PORT = Integer.toString(WsAgentLauncherImpl.WS_AGENT_PORT); + private static final String WS_AGENT_PORT = WsAgentLauncherImpl.WS_AGENT_PORT; private static final long WS_AGENT_MAX_START_TIME_MS = 1000; private static final long WS_AGENT_PING_DELAY_MS = 1; private static final int WS_AGENT_PING_CONN_TIMEOUT_MS = 1; diff --git a/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServletTest.java b/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServletTest.java index dd2a6de8527..b6101859a9e 100644 --- a/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServletTest.java +++ b/core/platform-api/che-core-api-machine/src/test/java/org/eclipse/che/api/machine/server/proxy/MachineExtensionProxyServletTest.java @@ -55,7 +55,7 @@ public class MachineExtensionProxyServletTest { private static final String WORKSPACE_ID = "workspace123"; - private static final int EXTENSIONS_API_PORT = 4301; + private static final String EXTENSIONS_API_PORT = "4301/tcp"; private static final String PROXY_ENDPOINT = "http://localhost:8080"; private static final String BASE_PATH = "/che/api/ext/api/"; private static final String DEFAULT_PATH = BASE_PATH + WORKSPACE_ID + "/java/"; @@ -143,7 +143,7 @@ public void setUpMethod() throws Exception { extensionApiRequest = new ExtensionApiRequest(); - proxyServlet = new MachineExtensionProxyServlet(4301, machineManager); + proxyServlet = new MachineExtensionProxyServlet(EXTENSIONS_API_PORT, machineManager); when(machineManager.getDevMachine(WORKSPACE_ID)).thenReturn(machine); when(machine.getRuntime()).thenReturn(machineRuntimeInfo); @@ -604,4 +604,4 @@ private static class ExtensionApiRequest { String uri; String query; } -} \ No newline at end of file +} diff --git a/core/platform-api/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidator.java b/core/platform-api/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidator.java index 49a826d96f2..9f177d3e385 100644 --- a/core/platform-api/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidator.java +++ b/core/platform-api/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidator.java @@ -13,10 +13,12 @@ import org.eclipse.che.api.core.BadRequestException; import org.eclipse.che.api.core.model.machine.Command; import org.eclipse.che.api.core.model.machine.MachineConfig; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.api.core.model.workspace.Environment; import org.eclipse.che.api.core.model.workspace.WorkspaceConfig; import javax.inject.Singleton; +import java.util.Map; import java.util.regex.Pattern; import static com.google.common.base.Strings.isNullOrEmpty; @@ -31,6 +33,8 @@ public class DefaultWorkspaceConfigValidator implements WorkspaceConfigValidator { /* should contain [3, 20] characters, first and last character is letter or digit, available characters {A-Za-z0-9.-_}*/ private static final Pattern WS_NAME = Pattern.compile("[a-zA-Z0-9][-_.a-zA-Z0-9]{1,18}[a-zA-Z0-9]"); + private static final Pattern SERVER_PORT = Pattern.compile("[1-9]+[0-9]*/(?:tcp|udp)"); + private static final Pattern SERVER_PROTOCOL = Pattern.compile("[a-z]{2,10}"); /** * Checks that workspace configuration is valid. @@ -71,34 +75,7 @@ public void validate(WorkspaceConfig config) throws BadRequestException { "Workspace default environment configuration required"); for (Environment environment : config.getEnvironments()) { - final String envName = environment.getName(); - checkArgument(!isNullOrEmpty(envName), "Environment name should be neither null nor empty"); - - checkArgument(environment.getRecipe() == null || "docker".equals(environment.getRecipe().getType()), - "Couldn't start workspace '%s' from environment '%s', environment recipe has unsupported type '%s'", - config.getName(), - envName, - environment.getRecipe() != null ? environment.getRecipe().getType() : null); - - //machine configs - checkArgument(!environment.getMachineConfigs().isEmpty(), "Environment '%s' should contain at least 1 machine", envName); - - final long devCount = environment.getMachineConfigs() - .stream() - .filter(MachineConfig::isDev) - .count(); - checkArgument(devCount == 1, - "Environment should contain exactly 1 dev machine, but '%s' contains '%d'", - envName, - devCount); - for (MachineConfig machineCfg : environment.getMachineConfigs()) { - checkArgument(!isNullOrEmpty(machineCfg.getName()), "Environment %s contains machine with null or empty name", envName); - checkNotNull(machineCfg.getSource(), "Environment " + envName + " contains machine without source"); - checkArgument("docker".equals(machineCfg.getType()), - "Type of machine %s in environment %s is not supported. Supported value is 'docker'.", - machineCfg.getName(), - envName); - } + validateEnv(environment, config.getName()); } //commands @@ -116,6 +93,56 @@ public void validate(WorkspaceConfig config) throws BadRequestException { //TODO } + private void validateEnv(Environment environment, String workspaceName) throws BadRequestException { + final String envName = environment.getName(); + checkArgument(!isNullOrEmpty(envName), "Environment name should be neither null nor empty"); + + checkArgument(environment.getRecipe() == null || "docker".equals(environment.getRecipe().getType()), + "Recipe of environment '%s' in workspace with name '%s' has unsupported type '%s'", + envName, + workspaceName, + environment.getRecipe() != null ? environment.getRecipe().getType() : null); + + //machine configs + checkArgument(!environment.getMachineConfigs().isEmpty(), "Environment '%s' should contain at least 1 machine", envName); + + final long devCount = environment.getMachineConfigs() + .stream() + .filter(MachineConfig::isDev) + .count(); + checkArgument(devCount == 1, + "Environment should contain exactly 1 dev machine, but '%s' contains '%d'", + envName, + devCount); + for (MachineConfig machineCfg : environment.getMachineConfigs()) { + validateMachine(machineCfg, envName); + } + } + + private void validateMachine(MachineConfig machineCfg, String envName) throws BadRequestException { + checkArgument(!isNullOrEmpty(machineCfg.getName()), "Environment %s contains machine with null or empty name", envName); + checkNotNull(machineCfg.getSource(), "Environment " + envName + " contains machine without source"); + checkArgument("docker".equals(machineCfg.getType()), + "Type of machine %s in environment %s is not supported. Supported value is 'docker'.", + machineCfg.getName(), + envName); + + for (ServerConf serverConf : machineCfg.getServers()) { + checkArgument(serverConf.getPort() != null && SERVER_PORT.matcher(serverConf.getPort()).matches(), + "Machine %s contains server conf with invalid port %s", + machineCfg.getName(), + serverConf.getPort()); + checkArgument(serverConf.getProtocol() == null || SERVER_PROTOCOL.matcher(serverConf.getProtocol()).matches(), + "Machine %s contains server conf with invalid protocol %s", + machineCfg.getName(), + serverConf.getProtocol()); + } + for (Map.Entry envVariable : machineCfg.getEnvVariables().entrySet()) { + checkArgument(!isNullOrEmpty(envVariable.getKey()), "Machine %s contains environment variable with null or empty name"); + checkNotNull(envVariable.getValue(), "Machine %s contains environment variable with null value"); + } + } + /** * Checks that object reference is not null, throws {@link BadRequestException} * in the case of null {@code object} with given {@code message}. diff --git a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidatorTest.java b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidatorTest.java index 388ff108bdf..74a66512fa0 100644 --- a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidatorTest.java +++ b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/DefaultWorkspaceConfigValidatorTest.java @@ -14,6 +14,7 @@ import org.eclipse.che.api.machine.shared.dto.CommandDto; import org.eclipse.che.api.machine.shared.dto.MachineConfigDto; import org.eclipse.che.api.machine.shared.dto.MachineSourceDto; +import org.eclipse.che.api.machine.shared.dto.ServerConfDto; import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto; import org.eclipse.che.api.workspace.shared.dto.RecipeDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; @@ -22,6 +23,7 @@ import org.testng.annotations.Test; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Optional; @@ -204,7 +206,7 @@ public void shouldFailValidationIfEnvNameIsEmpty() throws Exception { } @Test(expectedExceptions = BadRequestException.class, - expectedExceptionsMessageRegExp = "Couldn't start workspace '.*' from environment '.*', environment recipe has unsupported type '.*'") + expectedExceptionsMessageRegExp = "Recipe of environment '.*' in workspace with name '.*' has unsupported type '.*'") public void shouldFailValidationIfEnvironmentRecipeTypeIsNotDocker() throws Exception { final WorkspaceConfigDto config = createConfig(); config.getEnvironments() @@ -258,11 +260,11 @@ public void shouldFailValidationIfNoDevMachineFound() throws Exception { public void shouldFailValidationIf2DevMachinesFound() throws Exception { final WorkspaceConfigDto config = createConfig(); final Optional devMachine = config.getEnvironments() - .get(0) - .getMachineConfigs() - .stream() - .filter(MachineConfigDto::isDev) - .findAny(); + .get(0) + .getMachineConfigs() + .stream() + .filter(MachineConfigDto::isDev) + .findAny(); config.getEnvironments() .get(0) .getMachineConfigs() @@ -276,7 +278,11 @@ public void shouldFailValidationIf2DevMachinesFound() throws Exception { expectedExceptionsMessageRegExp = "Environment .* contains machine with null or empty name") public void shouldFailValidationIfMachineNameIsNull() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getEnvironments().get(0).getMachineConfigs().get(0).withName(null); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .withName(null); wsValidator.validate(config); @@ -286,7 +292,11 @@ public void shouldFailValidationIfMachineNameIsNull() throws Exception { expectedExceptionsMessageRegExp = "Environment .* contains machine with null or empty name") public void shouldFailValidationIfMachineNameIsEmpty() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getEnvironments().get(0).getMachineConfigs().get(0).withName(""); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .withName(""); wsValidator.validate(config); @@ -296,7 +306,11 @@ public void shouldFailValidationIfMachineNameIsEmpty() throws Exception { expectedExceptionsMessageRegExp = "Environment .* contains machine without source") public void shouldFailValidationIfMachineSourceIsNull() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getEnvironments().get(0).getMachineConfigs().get(0).withSource(null); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .withSource(null); wsValidator.validate(config); @@ -306,7 +320,11 @@ public void shouldFailValidationIfMachineSourceIsNull() throws Exception { expectedExceptionsMessageRegExp = "Type of machine .* in environment .* is not supported. Supported value is 'docker'.") public void shouldFailValidationIfMachineTypeIsNull() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getEnvironments().get(0).getMachineConfigs().get(0).withType(null); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .withType(null); wsValidator.validate(config); @@ -316,7 +334,11 @@ public void shouldFailValidationIfMachineTypeIsNull() throws Exception { expectedExceptionsMessageRegExp = "Type of machine .* in environment .* is not supported. Supported value is 'docker'.") public void shouldFailValidationIfMachineTypeIsNotDocker() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getEnvironments().get(0).getMachineConfigs().get(0).withType("compose"); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .withType("compose"); wsValidator.validate(config); @@ -326,7 +348,9 @@ public void shouldFailValidationIfMachineTypeIsNotDocker() throws Exception { expectedExceptionsMessageRegExp = "Workspace .* contains command with null or empty name") public void shouldFailValidationIfCommandNameIsNull() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getCommands().get(0).withName(null); + config.getCommands() + .get(0) + .withName(null); wsValidator.validate(config); @@ -336,7 +360,9 @@ public void shouldFailValidationIfCommandNameIsNull() throws Exception { expectedExceptionsMessageRegExp = "Workspace .* contains command with null or empty name") public void shouldFailValidationIfCommandNameIsEmpty() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getCommands().get(0).withName(null); + config.getCommands() + .get(0) + .withName(null); wsValidator.validate(config); @@ -346,7 +372,9 @@ public void shouldFailValidationIfCommandNameIsEmpty() throws Exception { expectedExceptionsMessageRegExp = "Command line required for command .* in workspace .*") public void shouldFailValidationIfCommandLineIsNull() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getCommands().get(0).withCommandLine(null); + config.getCommands() + .get(0) + .withCommandLine(null); wsValidator.validate(config); @@ -356,7 +384,125 @@ public void shouldFailValidationIfCommandLineIsNull() throws Exception { expectedExceptionsMessageRegExp = "Command line required for command .* in workspace .*") public void shouldFailValidationIfCommandLineIsEmpty() throws Exception { final WorkspaceConfigDto config = createConfig(); - config.getCommands().get(0).withCommandLine(""); + config.getCommands() + .get(0) + .withCommandLine(""); + + + wsValidator.validate(config); + } + + @Test(expectedExceptions = BadRequestException.class, + expectedExceptionsMessageRegExp = "Machine .* contains server conf with invalid port .*", + dataProvider = "invalidPortProvider") + public void shouldFailValidationIfServerConfPortIsInvalid(String invalidPort) throws Exception { + final WorkspaceConfigDto config = createConfig(); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .getServers() + .add(newDto(ServerConfDto.class).withPort(invalidPort)); + + + wsValidator.validate(config); + } + + @DataProvider(name = "invalidPortProvider") + public static Object[][] invalidPortProvider() { + return new Object[][] { + {"0"}, + {"0123"}, + {"012/tcp"}, + {"8080"}, + {"8080/pct"}, + {"8080/pdu"}, + {"/tcp"}, + {"tcp"}, + {""}, + {"8080/tcp1"}, + {"8080/tcpp"}, + {"8080tcp"}, + {"8080/tc"}, + {"8080/ud"}, + {"8080/udpp"}, + {"8080/udp/"}, + {"8080/tcp/"}, + {"8080/tcp/udp"}, + {"8080/tcp/tcp"}, + {"8080/tcp/8080"}, + {null} + }; + } + + @Test(expectedExceptions = BadRequestException.class, + expectedExceptionsMessageRegExp = "Machine .* contains server conf with invalid protocol .*", + dataProvider = "invalidProtocolProvider") + public void shouldFailValidationIfServerConfProtocolIsInvalid(String invalidProtocol) throws Exception { + final WorkspaceConfigDto config = createConfig(); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .getServers() + .add(newDto(ServerConfDto.class).withPort("8080/tcp") + .withProtocol(invalidProtocol)); + + + wsValidator.validate(config); + } + + @DataProvider(name = "invalidProtocolProvider") + public static Object[][] invalidProtocolProvider() { + return new Object[][] { + {""}, + {"http2"}, + {"h"}, + {"http2s"}, + {"httphttphttp"}, + }; + } + + @Test(expectedExceptions = BadRequestException.class, + expectedExceptionsMessageRegExp = "Machine %s contains environment variable with null or empty name") + public void shouldFailValidationIfEnvVarNameIsNull() throws Exception { + final WorkspaceConfigDto config = createConfig(); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .getEnvVariables() + .put(null, "value"); + + + wsValidator.validate(config); + } + + @Test(expectedExceptions = BadRequestException.class, + expectedExceptionsMessageRegExp = "Machine %s contains environment variable with null or empty name") + public void shouldFailValidationIfEnvVarNameIsEmpty() throws Exception { + final WorkspaceConfigDto config = createConfig(); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .getEnvVariables() + .put("", "value"); + + + wsValidator.validate(config); + } + + @Test(expectedExceptions = BadRequestException.class, + expectedExceptionsMessageRegExp = "Machine %s contains environment variable with null value") + public void shouldFailValidationIfEnvVarValueIsNull() throws Exception { + final WorkspaceConfigDto config = createConfig(); + config.getEnvironments() + .get(0) + .getMachineConfigs() + .get(0) + .getEnvVariables() + .put("key", null); wsValidator.validate(config); @@ -366,11 +512,19 @@ private static WorkspaceConfigDto createConfig() { final WorkspaceConfigDto workspaceConfigDto = newDto(WorkspaceConfigDto.class).withName("ws-name") .withDefaultEnv("dev-env"); + final List serversConf = new ArrayList<>(Arrays.asList(newDto(ServerConfDto.class).withRef("ref1") + .withPort("8080/tcp") + .withProtocol("https"), + newDto(ServerConfDto.class).withRef("ref2") + .withPort("9090/udp") + .withProtocol("protocol"))); MachineConfigDto devMachine = newDto(MachineConfigDto.class).withDev(true) .withName("dev-machine") .withType("docker") .withSource(newDto(MachineSourceDto.class).withLocation("location") - .withType("recipe")); + .withType("recipe")) + .withServers(serversConf) + .withEnvVariables(new HashMap<>(singletonMap("key1", "value1"))); EnvironmentDto devEnv = newDto(EnvironmentDto.class).withName("dev-env") .withMachineConfigs(new ArrayList<>(singletonList(devMachine))) .withRecipe(null); diff --git a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java index 6099d52f018..43574b91cfe 100644 --- a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java +++ b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java @@ -21,6 +21,7 @@ import org.eclipse.che.api.machine.server.impl.SnapshotImpl; import org.eclipse.che.api.machine.shared.dto.MachineConfigDto; import org.eclipse.che.api.machine.shared.dto.MachineSourceDto; +import org.eclipse.che.api.machine.shared.dto.ServerConfDto; import org.eclipse.che.api.workspace.server.model.impl.RuntimeWorkspaceImpl; import org.eclipse.che.api.workspace.server.model.impl.UsersWorkspaceImpl; import org.eclipse.che.api.workspace.server.spi.WorkspaceDao; @@ -38,6 +39,8 @@ import org.testng.annotations.Test; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import static com.google.common.base.Strings.isNullOrEmpty; @@ -480,11 +483,19 @@ private RuntimeWorkspaceImpl createRuntime(UsersWorkspace workspace) { } private static WorkspaceConfigDto createConfig() { - MachineConfigDto devMachine = newDto(MachineConfigDto.class).withDev(true) - .withName("dev-machine") - .withType("docker") - .withSource(newDto(MachineSourceDto.class).withLocation("location") - .withType("recipe")); + MachineConfigDto devMachine = + newDto(MachineConfigDto.class).withDev(true) + .withName("dev-machine") + .withType("docker") + .withSource(newDto(MachineSourceDto.class).withLocation("location") + .withType("recipe")) + .withServers(Arrays.asList(newDto(ServerConfDto.class).withRef("ref1") + .withPort("8080") + .withProtocol("https"), + newDto(ServerConfDto.class).withRef("ref2") + .withPort("9090/udp") + .withProtocol("someprotocol"))) + .withEnvVariables(Collections.singletonMap("key1", "value1")); EnvironmentDto devEnv = newDto(EnvironmentDto.class).withName("dev-env") .withMachineConfigs(new ArrayList<>(singletonList(devMachine))) .withRecipe(null); diff --git a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackLoaderTest.java b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackLoaderTest.java index d98f524c3e5..0c5cba6b8e5 100644 --- a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackLoaderTest.java +++ b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackLoaderTest.java @@ -32,6 +32,7 @@ import org.eclipse.che.api.machine.shared.dto.LimitsDto; import org.eclipse.che.api.machine.shared.dto.MachineConfigDto; import org.eclipse.che.api.machine.shared.dto.MachineSourceDto; +import org.eclipse.che.api.machine.shared.dto.ServerConfDto; import org.eclipse.che.api.workspace.server.model.stack.StackComponent; import org.eclipse.che.api.workspace.server.model.stack.StackSource; import org.eclipse.che.api.workspace.server.spi.StackDao; @@ -185,11 +186,18 @@ public void dtoShouldBeSerialized() { MachineSourceDto machineSourceDto = newDto(MachineSourceDto.class).withLocation("location").withType("type"); - MachineConfigDto machineConfig = newDto(MachineConfigDto.class).withDev(true) - .withName("machine config name") - .withType("type") - .withLimits(limitsDto) - .withSource(machineSourceDto); + MachineConfigDto machineConfig = + newDto(MachineConfigDto.class).withDev(true) + .withName("machine config name") + .withType("type") + .withLimits(limitsDto) + .withSource(machineSourceDto) + .withServers(Arrays.asList(newDto(ServerConfDto.class).withRef("ref1") + .withPort("8080") + .withProtocol("https"), + newDto(ServerConfDto.class).withRef("ref2") + .withPort("9090/udp") + .withProtocol("someprotocol"))); EnvironmentDto environmentDto = newDto(EnvironmentDto.class).withName("name") .withRecipe(recipeDto) diff --git a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackServiceTest.java b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackServiceTest.java index de39a702062..cadf77a1d1b 100644 --- a/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackServiceTest.java +++ b/core/platform-api/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/stack/StackServiceTest.java @@ -22,6 +22,7 @@ import org.eclipse.che.api.machine.server.model.impl.LimitsImpl; import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl; import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.api.machine.server.recipe.PermissionsChecker; import org.eclipse.che.api.machine.shared.Permissible; import org.eclipse.che.api.machine.shared.dto.recipe.GroupDescriptor; @@ -59,6 +60,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.net.URISyntaxException; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; @@ -170,7 +172,14 @@ public void setUp() throws IOException, ConflictException { MachineSourceImpl machineSource = new MachineSourceImpl(MACHINE_SOURCE_TYPE, MACHINE_SOURCE_LOCATION); int limitMemory = 1000; LimitsImpl limits = new LimitsImpl(limitMemory); - MachineConfigImpl machineConfig = new MachineConfigImpl(IS_DEV, MACHINE_CONFIG_NAME, MACHINE_TYPE, machineSource, limits); + MachineConfigImpl machineConfig = new MachineConfigImpl(IS_DEV, + MACHINE_CONFIG_NAME, + MACHINE_TYPE, + machineSource, + limits, + Arrays.asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")); EnvironmentImpl environment = new EnvironmentImpl(ENVIRONMENT_NAME, null, Collections.singletonList(machineConfig)); WorkspaceConfigImpl workspaceConfig = WorkspaceConfigImpl.builder() diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstance.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstance.java index dff3f2f49e9..0f1a9c0b2bc 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstance.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstance.java @@ -117,10 +117,13 @@ public LineConsumer getLogger() { @Override public MachineRuntimeInfoImpl getRuntime() { + // if runtime info is not evaluated yet if (machineRuntime == null) { try { final ContainerInfo containerInfo = docker.inspectContainer(container); - machineRuntime = new MachineRuntimeInfoImpl(dockerMachineFactory.createMetadata(containerInfo, node.getHost())); + machineRuntime = new MachineRuntimeInfoImpl(dockerMachineFactory.createMetadata(containerInfo, + node.getHost(), + getConfig())); } catch (IOException e) { LOG.error(e.getLocalizedMessage(), e); return null; diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProvider.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProvider.java index 6a371accd1e..4f0f7251cba 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProvider.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProvider.java @@ -19,6 +19,7 @@ import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.model.machine.Machine; import org.eclipse.che.api.core.model.machine.Recipe; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.api.core.util.FileCleaner; import org.eclipse.che.api.core.util.LineConsumer; import org.eclipse.che.api.core.util.SystemInfo; @@ -53,7 +54,9 @@ import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -78,14 +81,12 @@ public class DockerInstanceProvider implements InstanceProvider { private final boolean doForcePullOnBuild; private final Set supportedRecipeTypes; private final DockerMachineFactory dockerMachineFactory; - private final Map devMachineContainerLabels; - private final Map commonMachineContainerLabels; private final Map> devMachinePortsToExpose; private final Map> commonMachinePortsToExpose; private final String[] devMachineSystemVolumes; private final String[] commonMachineSystemVolumes; - private final String[] devMachineEnvVariables; - private final String[] commonMachineEnvVariables; + private final Set devMachineEnvVariables; + private final Set commonMachineEnvVariables; private final String[] allMachinesExtraHosts; private final String projectFolderPath; @@ -127,30 +128,22 @@ public DockerInstanceProvider(DockerConnector docker, this.devMachinePortsToExpose = Maps.newHashMapWithExpectedSize(allMachinesServers.size() + devMachineServers.size()); this.commonMachinePortsToExpose = Maps.newHashMapWithExpectedSize(allMachinesServers.size()); - this.devMachineContainerLabels = Maps.newHashMapWithExpectedSize(2 * allMachinesServers.size() + 2 * devMachineServers.size()); - this.commonMachineContainerLabels = Maps.newHashMapWithExpectedSize(2 * allMachinesServers.size()); for (ServerConf serverConf : devMachineServers) { - devMachinePortsToExpose.put(serverConf.getPort(), Collections.emptyMap()); - devMachineContainerLabels.put("che:server:" + serverConf.getPort() + ":ref", serverConf.getRef()); - devMachineContainerLabels.put("che:server:" + serverConf.getPort() + ":protocol", serverConf.getProtocol()); + devMachinePortsToExpose.put(serverConf.getPort(), Collections.emptyMap()); } for (ServerConf serverConf : allMachinesServers) { - commonMachinePortsToExpose.put(serverConf.getPort(), Collections.emptyMap()); - devMachinePortsToExpose.put(serverConf.getPort(), Collections.emptyMap()); - commonMachineContainerLabels.put("che:server:" + serverConf.getPort() + ":ref", serverConf.getRef()); - devMachineContainerLabels.put("che:server:" + serverConf.getPort() + ":ref", serverConf.getRef()); - commonMachineContainerLabels.put("che:server:" + serverConf.getPort() + ":protocol", serverConf.getProtocol()); - devMachineContainerLabels.put("che:server:" + serverConf.getPort() + ":protocol", serverConf.getProtocol()); + commonMachinePortsToExpose.put(serverConf.getPort(), Collections.emptyMap()); + devMachinePortsToExpose.put(serverConf.getPort(), Collections.emptyMap()); } allMachinesEnvVariables = filterEmptyAndNullValues(allMachinesEnvVariables); devMachineEnvVariables = filterEmptyAndNullValues(devMachineEnvVariables); - this.commonMachineEnvVariables = allMachinesEnvVariables.toArray(new String[allMachinesEnvVariables.size()]); + this.commonMachineEnvVariables = allMachinesEnvVariables; final HashSet envVariablesForDevMachine = Sets.newHashSetWithExpectedSize(allMachinesEnvVariables.size() + devMachineEnvVariables.size()); envVariablesForDevMachine.addAll(allMachinesEnvVariables); envVariablesForDevMachine.addAll(devMachineEnvVariables); - this.devMachineEnvVariables = envVariablesForDevMachine.toArray(new String[envVariablesForDevMachine.size()]); + this.devMachineEnvVariables = envVariablesForDevMachine; // always add the docker host String dockerHost = DockerInstanceRuntimeInfo.CHE_HOST.concat(":").concat(dockerConnectorConfiguration.getDockerHostIp()); @@ -264,7 +257,8 @@ private Dockerfile parseRecipe(Recipe recipe) throws InvalidRecipeException { throw new InvalidRecipeException("Unable build docker based machine, Dockerfile found but it doesn't contain base image."); } if (dockerfile.getImages().size() > 1) { - throw new InvalidRecipeException("Unable build docker based machine, Dockerfile found but it contains more than one instruction 'FROM'."); + throw new InvalidRecipeException( + "Unable build docker based machine, Dockerfile found but it contains more than one instruction 'FROM'."); } return dockerfile; } @@ -390,13 +384,11 @@ private Instance createInstance(String containerName, LineConsumer outputConsumer) throws MachineException { try { - final Map labels; final Map> portsToExpose; final String[] volumes; - final String[] env; + final List env; if (machine.getConfig().isDev()) { - labels = devMachineContainerLabels; - portsToExpose = devMachinePortsToExpose; + portsToExpose = new HashMap<>(devMachinePortsToExpose); final String projectFolderVolume = String.format("%s:%s", workspaceFolderPathProvider.getPath(machine.getWorkspaceId()), @@ -404,16 +396,25 @@ private Instance createInstance(String containerName, volumes = ObjectArrays.concat(devMachineSystemVolumes, SystemInfo.isWindows() ? escapePath(projectFolderVolume) : projectFolderVolume); - String[] vars = {DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + '=' + machine.getWorkspaceId(), - DockerInstanceRuntimeInfo.USER_TOKEN + '=' + EnvironmentContext.getCurrent().getUser().getToken()}; - env = ObjectArrays.concat(devMachineEnvVariables, vars, String.class); - + env = new ArrayList<>(devMachineEnvVariables); + env.add(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + '=' + machine.getWorkspaceId()); + env.add(DockerInstanceRuntimeInfo.USER_TOKEN + '=' + EnvironmentContext.getCurrent().getUser().getToken()); } else { - labels = commonMachineContainerLabels; - portsToExpose = commonMachinePortsToExpose; + portsToExpose = new HashMap<>(commonMachinePortsToExpose); volumes = commonMachineSystemVolumes; - env = commonMachineEnvVariables; + env = new ArrayList<>(commonMachineEnvVariables); } + machine.getConfig() + .getServers() + .stream() + .forEach(serverConf -> portsToExpose.put(serverConf.getPort(), Collections.emptyMap())); + + machine.getConfig() + .getEnvVariables() + .entrySet() + .stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .forEach(env::add); final HostConfig hostConfig = new HostConfig().withBinds(volumes) .withExtraHosts(allMachinesExtraHosts) @@ -421,10 +422,9 @@ private Instance createInstance(String containerName, .withMemorySwap(-1) .withMemory((long)machine.getConfig().getLimits().getRam() * 1024 * 1024); final ContainerConfig config = new ContainerConfig().withImage(imageName) - .withLabels(labels) .withExposedPorts(portsToExpose) .withHostConfig(hostConfig) - .withEnv(env); + .withEnv(env.toArray(new String[env.size()])); final String containerId = docker.createContainer(config, containerName).getId(); diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfo.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfo.java index a07b20f8aa3..e3fa5a2084c 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfo.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfo.java @@ -12,20 +12,25 @@ import com.google.inject.assistedinject.Assisted; +import org.eclipse.che.api.core.model.machine.MachineConfig; import org.eclipse.che.api.core.model.machine.MachineRuntimeInfo; -import org.eclipse.che.api.core.model.machine.Server; +import org.eclipse.che.api.core.model.machine.ServerConf; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.api.machine.server.model.impl.ServerImpl; import org.eclipse.che.plugin.docker.client.json.ContainerInfo; import org.eclipse.che.plugin.docker.client.json.PortBinding; import javax.inject.Inject; +import javax.inject.Named; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.Set; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toMap; /** * Docker implementation of {@link MachineRuntimeInfo} @@ -60,16 +65,31 @@ public class DockerInstanceRuntimeInfo implements MachineRuntimeInfo { */ public static final String USER_TOKEN = "USER_TOKEN"; - protected static final Pattern SERVICE_LABEL_PATTERN = - Pattern.compile("che:server:(?[0-9]+(/tcp|/udp)?):(?ref|protocol)"); + protected static final String SERVER_CONF_LABEL_PREFIX = "che:server:"; + protected static final String SERVER_CONF_LABEL_REF_SUFFIX = ":ref"; + protected static final String SERVER_CONF_LABEL_PROTOCOL_SUFFIX = ":protocol"; - private final ContainerInfo info; - private final String containerHost; + private final ContainerInfo info; + private final String containerHost; + private final Map serversConf; @Inject - public DockerInstanceRuntimeInfo(@Assisted ContainerInfo containerInfo, @Assisted String containerHost) { + public DockerInstanceRuntimeInfo(@Assisted ContainerInfo containerInfo, + @Assisted String containerHost, + @Assisted MachineConfig machineConfig, + @Named("machine.docker.dev_machine.machine_servers") Set devMachineSystemServers, + @Named("machine.docker.machine_servers") Set allMachinesSystemServers) { this.info = containerInfo; this.containerHost = containerHost; + Stream confStream = Stream.concat(machineConfig.getServers().stream(), allMachinesSystemServers.stream()); + if (machineConfig.isDev()) { + confStream = Stream.concat(confStream, devMachineSystemServers.stream()); + } + // convert list to map for quick search and normalize port - add /tcp if missing + this.serversConf = confStream.collect(toMap(srvConf -> srvConf.getPort().contains("/") ? + srvConf.getPort() : + srvConf.getPort() + "/tcp", + ServerConfImpl::new)); } @Override @@ -182,59 +202,79 @@ public String projectsRoot() { } @Override - public Map getServers() { + public Map getServers() { return addDefaultReferenceForServersWithoutReference( - addRefAndUrlToServerFromImageLabels(getServersWithFilledPorts(containerHost, - info.getNetworkSettings().getPorts()), - info.getConfig().getLabels())); + addRefAndUrlToServers(getServersWithFilledPorts(containerHost, + info.getNetworkSettings().getPorts()), + info.getConfig().getLabels())); } - private Map addDefaultReferenceForServersWithoutReference(Map servers) { + private Map addDefaultReferenceForServersWithoutReference(Map servers) { // replace / if server port contains it. E.g. 5411/udp servers.entrySet() .stream() .filter(server -> server.getValue().getRef() == null) .forEach(server -> { // replace / if server port contains it. E.g. 5411/udp - ((ServerImpl)server.getValue()).setRef("Server-" + server.getKey().replace("/", "-")); + server.getValue().setRef("Server-" + server.getKey().replace("/", "-")); }); return servers; } - protected HashMap getServersWithFilledPorts(final String host, final Map> exposedPorts) { - final HashMap servers = new LinkedHashMap<>(); + protected Map addRefAndUrlToServers(final Map servers, final Map labels) { + final Map serversConfFromLabels = getServersConfFromLabels(servers.keySet(), labels); + for (Map.Entry serverEntry : servers.entrySet()) { + ServerConf serverConf = serversConf.getOrDefault(serverEntry.getKey(), serversConfFromLabels.get(serverEntry.getKey())); + if (serverConf != null) { + if (serverConf.getRef() != null) { + serverEntry.getValue().setRef(serverConf.getRef()); + } + if (serverConf.getProtocol() != null) { + serverEntry.getValue().setUrl(serverConf.getProtocol() + "://" + serverEntry.getValue().getAddress()); + } + } + } + + return servers; + } + + protected Map getServersWithFilledPorts(final String host, final Map> exposedPorts) { + final HashMap servers = new LinkedHashMap<>(); for (Map.Entry> portEntry : exposedPorts.entrySet()) { - // in form 1234/tcp or 1234 - String portOrPortUdp = portEntry.getKey(); + // in form 1234/tcp + String portProtocol = portEntry.getKey(); // we are assigning ports automatically, so have 1 to 1 binding (at least per protocol) - if (!portOrPortUdp.endsWith("/udp")) { - // cut off /tcp if it presents - portOrPortUdp = portOrPortUdp.split("/", 2)[0]; - } - final PortBinding portBinding = portEntry.getValue().get(0); - servers.put(portOrPortUdp, new ServerImpl(null, host + ":" + portBinding.getHostPort(), null)); + String externalPort = portEntry.getValue().get(0).getHostPort(); + servers.put(portProtocol, new ServerImpl(null, + host + ":" + externalPort, + null)); } return servers; } - protected Map addRefAndUrlToServerFromImageLabels(final Map servers, final Map labels) { - for (Map.Entry label : labels.entrySet()) { - final Matcher matcher = SERVICE_LABEL_PATTERN.matcher(label.getKey()); - if (matcher.matches()) { - final String port = matcher.group("port"); - if (servers.containsKey(port)) { - final ServerImpl server = (ServerImpl)servers.get(port); - if ("ref".equals(matcher.group("servprop"))) { - server.setRef(label.getValue()); - } else { - // value is protocol - server.setUrl(label.getValue() + "://" + server.getAddress()); - } - } + private Map getServersConfFromLabels(final Set portProtocols, final Map labels) { + final HashMap serversConf = new LinkedHashMap<>(); + for (String portProtocol : portProtocols) { + String ref = labels.get(SERVER_CONF_LABEL_PREFIX + portProtocol + SERVER_CONF_LABEL_REF_SUFFIX); + String protocol = labels.get(SERVER_CONF_LABEL_PREFIX + portProtocol + SERVER_CONF_LABEL_PROTOCOL_SUFFIX); + // it is allowed to use label without part /tcp that describes tcp port, e.g. 8080 describes 8080/tcp + if (ref == null && !portProtocol.endsWith("/udp")) { + ref = labels.get(SERVER_CONF_LABEL_PREFIX + + portProtocol.substring(0, portProtocol.length() - 4) + + SERVER_CONF_LABEL_REF_SUFFIX); } + if (protocol == null && !portProtocol.endsWith("/udp")) { + protocol = labels.get(SERVER_CONF_LABEL_PREFIX + + portProtocol.substring(0, portProtocol.length() - 4) + + SERVER_CONF_LABEL_PROTOCOL_SUFFIX); + } + serversConf.put(portProtocol, new ServerConfImpl(ref, + portProtocol, + protocol)); } - return servers; + + return serversConf; } } diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineFactory.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineFactory.java index 0280aa01177..1ed6becb41e 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineFactory.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineFactory.java @@ -14,6 +14,7 @@ import org.eclipse.che.api.core.model.machine.Command; import org.eclipse.che.api.core.model.machine.Machine; +import org.eclipse.che.api.core.model.machine.MachineConfig; import org.eclipse.che.api.core.util.LineConsumer; import org.eclipse.che.api.machine.server.exception.MachineException; import org.eclipse.che.api.machine.server.spi.Instance; @@ -80,7 +81,9 @@ DockerNode createNode(@Assisted("workspace") String workspaceId, * * @param containerInfo description of docker container * @param containerHost host where docker container is placed + * @param machineConfig config of machine */ DockerInstanceRuntimeInfo createMetadata(@Assisted ContainerInfo containerInfo, - @Assisted String containerHost); + @Assisted String containerHost, + @Assisted MachineConfig machineConfig); } diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineModule.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineModule.java index 6c1c54ea251..efd7f715747 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineModule.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/DockerMachineModule.java @@ -14,6 +14,8 @@ import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; +import org.eclipse.che.api.core.model.machine.ServerConf; + /** * Module for components that are needed for {@link DockerInstanceProvider} * @@ -37,8 +39,8 @@ protected void configure() { .permitDuplicates(); Multibinder devMachineServers = Multibinder.newSetBinder(binder(), - ServerConf.class, - Names.named("machine.docker.dev_machine.machine_servers")); + ServerConf.class, + Names.named("machine.docker.dev_machine.machine_servers")); Multibinder machineServers = Multibinder.newSetBinder(binder(), ServerConf.class, Names.named("machine.docker.machine_servers")); diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ServerConf.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ServerConf.java deleted file mode 100644 index c8efdaa61d9..00000000000 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ServerConf.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012-2016 Codenvy, S.A. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Codenvy, S.A. - initial API and implementation - *******************************************************************************/ -package org.eclipse.che.plugin.docker.machine; - -import com.google.common.base.Objects; - -/** - * Describes configuration of the Che server in machine - * - * @author Alexander Garagatyi - */ -public class ServerConf { - private String ref; - private String port; - private String protocol; - - public ServerConf() { - } - - public ServerConf(String ref, String port, String protocol) { - this.ref = ref; - this.port = port; - this.protocol = protocol; - } - - public String getRef() { - return ref; - } - - public ServerConf setRef(String ref) { - this.ref = ref; - return this; - } - - public String getPort() { - return port; - } - - public ServerConf setPort(String port) { - this.port = port; - return this; - } - - public String getProtocol() { - return protocol; - } - - public ServerConf setProtocol(String protocol) { - this.protocol = protocol; - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ServerConf)) return false; - ServerConf that = (ServerConf)o; - return Objects.equal(port, that.port) && - Objects.equal(ref, that.ref) && - Objects.equal(protocol, that.protocol); - } - - @Override - public int hashCode() { - return Objects.hashCode(ref, port, protocol); - } -} diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerExtServerModule.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerExtServerModule.java index c43598d60ab..9e2c47e859a 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerExtServerModule.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerExtServerModule.java @@ -14,8 +14,8 @@ import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.inject.CheBootstrap; -import org.eclipse.che.plugin.docker.machine.ServerConf; import org.eclipse.che.plugin.docker.machine.ext.provider.WsAgentServerConfProvider; /** diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerTerminalModule.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerTerminalModule.java index 7f716fe5fa1..9b1b41478d2 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerTerminalModule.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/DockerTerminalModule.java @@ -14,7 +14,7 @@ import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; -import org.eclipse.che.plugin.docker.machine.ServerConf; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.plugin.docker.machine.ext.provider.TerminalServerConfProvider; /** diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/TerminalServerConfProvider.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/TerminalServerConfProvider.java index 9296ef04215..98093871feb 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/TerminalServerConfProvider.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/TerminalServerConfProvider.java @@ -11,7 +11,8 @@ package org.eclipse.che.plugin.docker.machine.ext.provider; -import org.eclipse.che.plugin.docker.machine.ServerConf; +import org.eclipse.che.api.core.model.machine.ServerConf; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import javax.inject.Inject; import javax.inject.Named; @@ -34,6 +35,6 @@ public class TerminalServerConfProvider implements Provider { @Override public ServerConf get() { - return new ServerConf(TERMINAL_SERVER_REFERENCE, "4411", apiEndpoint.getScheme()); + return new ServerConfImpl(TERMINAL_SERVER_REFERENCE, "4411/tcp", apiEndpoint.getScheme()); } } diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/WsAgentServerConfProvider.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/WsAgentServerConfProvider.java index 0202efc3624..dfb01564cd8 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/WsAgentServerConfProvider.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/ext/provider/WsAgentServerConfProvider.java @@ -8,11 +8,11 @@ * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ - package org.eclipse.che.plugin.docker.machine.ext.provider; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.api.machine.server.WsAgentLauncherImpl; -import org.eclipse.che.plugin.docker.machine.ServerConf; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import javax.inject.Inject; import javax.inject.Named; @@ -36,6 +36,8 @@ public class WsAgentServerConfProvider implements Provider { @Override public ServerConf get() { - return new ServerConf(WS_AGENT_SERVER_REFERENCE, Integer.toString(WsAgentLauncherImpl.WS_AGENT_PORT), apiEndpoint.getScheme()); + return new ServerConfImpl(WS_AGENT_SERVER_REFERENCE, + WsAgentLauncherImpl.WS_AGENT_PORT, + apiEndpoint.getScheme()); } } diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/local/LocalDockerInstanceRuntimeInfo.java b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/local/LocalDockerInstanceRuntimeInfo.java index 1545fefb151..ab68438c12a 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/local/LocalDockerInstanceRuntimeInfo.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/main/java/org/eclipse/che/plugin/docker/machine/local/LocalDockerInstanceRuntimeInfo.java @@ -12,12 +12,16 @@ import com.google.inject.assistedinject.Assisted; +import org.eclipse.che.api.core.model.machine.MachineConfig; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.plugin.docker.client.json.ContainerInfo; import org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo; import javax.inject.Inject; import javax.inject.Named; +import java.util.List; +import java.util.Set; /** * Gets predefined docker containers host for machine servers instead of evaluating it from docker configuration @@ -27,7 +31,7 @@ * Environment variable has lower priority. * * @author Alexander Garagatyi - * @see org.eclipse.che.plugin.docker.machine.ServerConf + * @see org.eclipse.che.api.core.model.machine.ServerConf */ public class LocalDockerInstanceRuntimeInfo extends DockerInstanceRuntimeInfo { /** @@ -38,8 +42,16 @@ public class LocalDockerInstanceRuntimeInfo extends DockerInstanceRuntimeInfo { @Inject public LocalDockerInstanceRuntimeInfo(@Assisted ContainerInfo containerInfo, @Assisted String containerHost, - @Nullable @Named("machine.docker.local_node_host") String dockerNodeHost) { - super(containerInfo, dockerNodeHost != null ? dockerNodeHost : - (System.getenv(CHE_DOCKER_MACHINE_HOST) != null ? System.getenv(CHE_DOCKER_MACHINE_HOST) : containerHost)); + @Assisted MachineConfig machineConfig, + @Nullable @Named("machine.docker.local_node_host") String dockerNodeHost, + @Named("machine.docker.dev_machine.machine_servers") Set devMachineServers, + @Named("machine.docker.machine_servers") Set allMachinesServers) { + super(containerInfo, + dockerNodeHost != null ? dockerNodeHost : (System.getenv(CHE_DOCKER_MACHINE_HOST) != null ? + System.getenv(CHE_DOCKER_MACHINE_HOST) : + containerHost), + machineConfig, + devMachineServers, + allMachinesServers); } } diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProviderTest.java b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProviderTest.java index 110a9cd88e4..e0f2c20357a 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProviderTest.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceProviderTest.java @@ -12,15 +12,16 @@ import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.model.machine.Machine; -import org.eclipse.che.api.core.model.machine.MachineSource; import org.eclipse.che.api.core.model.machine.MachineStatus; import org.eclipse.che.api.core.model.machine.Recipe; +import org.eclipse.che.api.core.model.machine.ServerConf; import org.eclipse.che.api.core.util.LineConsumer; import org.eclipse.che.api.machine.server.exception.MachineException; import org.eclipse.che.api.machine.server.model.impl.LimitsImpl; import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl; import org.eclipse.che.api.machine.server.model.impl.MachineImpl; import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.api.machine.server.recipe.RecipeImpl; import org.eclipse.che.commons.env.EnvironmentContext; import org.eclipse.che.commons.user.UserImpl; @@ -46,10 +47,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyString; @@ -114,6 +118,7 @@ public void setUp() throws Exception { EnvironmentContext envCont = new EnvironmentContext(); envCont.setUser(new UserImpl("user", "userId", USER_TOKEN, null, false)); + envCont.setWorkspaceId(WORKSPACE_ID); EnvironmentContext.setCurrent(envCont); when(dockerMachineFactory.createNode(anyString(), anyString())).thenReturn(dockerNode); @@ -231,17 +236,21 @@ public void shouldCallCreationDockerInstanceWithFactoryOnCreateInstanceFromSnaps doReturn(generatedContainerId).when(dockerInstanceProvider).generateContainerName(eq(WORKSPACE_ID), eq(DISPLAY_NAME)); final MachineSourceImpl machineSource = new MachineSourceImpl("type", "location"); - final MachineImpl machine = new MachineImpl(new MachineConfigImpl(false, - DISPLAY_NAME, - "machineType", - machineSource, - new LimitsImpl(MEMORY_LIMIT_MB)), - "machineId", - WORKSPACE_ID, - "envName", - "userId", - MachineStatus.CREATING, - null); + final MachineImpl machine = + new MachineImpl(new MachineConfigImpl(false, + DISPLAY_NAME, + "machineType", + machineSource, + new LimitsImpl(MEMORY_LIMIT_MB), + asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")), + "machineId", + WORKSPACE_ID, + "envName", + "userId", + MachineStatus.CREATING, + null); createInstanceFromSnapshot(machine); @@ -261,17 +270,21 @@ public void shouldCallCreationDockerInstanceWithFactoryOnCreateInstanceFromRecip final MachineSourceImpl machineSource = new MachineSourceImpl("type", "location"); final Recipe recipe = new RecipeImpl().withType("Dockerfile").withScript("FROM busybox"); - final MachineImpl machine = new MachineImpl(new MachineConfigImpl(false, - DISPLAY_NAME, - "machineType", - machineSource, - new LimitsImpl(MEMORY_LIMIT_MB)), - "machineId", - WORKSPACE_ID, - "envName", - "userId", - MachineStatus.CREATING, - null); + final MachineImpl machine = + new MachineImpl(new MachineConfigImpl(false, + DISPLAY_NAME, + "machineType", + machineSource, + new LimitsImpl(MEMORY_LIMIT_MB), + asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", "someprotocol")), + Collections.singletonMap("key1", "value1")), + "machineId", + WORKSPACE_ID, + "envName", + "userId", + MachineStatus.CREATING, + null); createInstanceFromRecipe(recipe, machine); @@ -380,21 +393,19 @@ public void shouldDisableSwapMemorySizeInContainersOnInstanceCreationFromSnapsho } @Test - public void shouldAddCommonAndDevLabelsToContainerOnDevInstanceCreationFromRecipe() throws Exception { - final Map expectedLabels = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedLabels.put("che:server:" + server.getPort() + ":ref", server.getRef()); - expectedLabels.put("che:server:" + server.getPort() + ":protocol", server.getProtocol()); - } - - final Set devServers = new HashSet<>(asList(new ServerConf("reference3", "8082", "https"), - new ServerConf("reference4", "8083", "sftp"))); - for (ServerConf server : devServers) { - expectedLabels.put("che:server:" + server.getPort() + ":ref", server.getRef()); - expectedLabels.put("che:server:" + server.getPort() + ":protocol", server.getProtocol()); - } + public void shouldExposeCommonAndDevPortsToContainerOnDevInstanceCreationFromRecipe() throws Exception { + List expectedExposedPorts = new ArrayList<>(); + final Set commonServers = new HashSet<>(asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp"))); + expectedExposedPorts.addAll(commonServers.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); + + final Set devServers = new HashSet<>(asList(new ServerConfImpl("reference3", "8082", "https"), + new ServerConfImpl("reference4", "8083", "sftp"))); + expectedExposedPorts.addAll(devServers.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, @@ -419,27 +430,24 @@ public void shouldAddCommonAndDevLabelsToContainerOnDevInstanceCreationFromRecip ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getLabels(), expectedLabels); + + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldAddOnlyCommonLabelsToContainerOnNonDevInstanceCreationFromRecipe() throws Exception { - final Map expectedLabels = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedLabels.put("che:server:" + server.getPort() + ":ref", server.getRef()); - expectedLabels.put("che:server:" + server.getPort() + ":protocol", server.getProtocol()); - } - - final Set devServers = new HashSet<>(asList(new ServerConf("reference3", "8082", "https"), - new ServerConf("reference4", "8083", "sftp"))); + public void shouldExposeOnlyCommonPortsToContainerOnNonDevInstanceCreationFromRecipe() throws Exception { + List expectedExposedPorts = new ArrayList<>(); + final Set commonServers = new HashSet<>(asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp"))); + expectedExposedPorts.addAll(commonServers.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, dockerMachineFactory, dockerInstanceStopDetector, - devServers, + Collections.emptySet(), commonServers, Collections.emptySet(), Collections.emptySet(), @@ -458,25 +466,24 @@ public void shouldAddOnlyCommonLabelsToContainerOnNonDevInstanceCreationFromReci ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getLabels(), expectedLabels); + + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldAddCommonAndDevLabelsToContainerOnDevInstanceCreationFromSnapshot() throws Exception { - final Map expectedLabels = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedLabels.put("che:server:" + server.getPort() + ":ref", server.getRef()); - expectedLabels.put("che:server:" + server.getPort() + ":protocol", server.getProtocol()); - } - - final Set devServers = new HashSet<>(asList(new ServerConf("reference3", "8082", "https"), - new ServerConf("reference4", "8083", "sftp"))); - for (ServerConf server : devServers) { - expectedLabels.put("che:server:" + server.getPort() + ":ref", server.getRef()); - expectedLabels.put("che:server:" + server.getPort() + ":protocol", server.getProtocol()); - } + public void shouldExposeCommonAndDevPortsToContainerOnDevInstanceCreationFromSnapshot() throws Exception { + List expectedExposedPorts = new ArrayList<>(); + final Set commonServers = new HashSet<>(asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp"))); + expectedExposedPorts.addAll(commonServers.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); + + final Set devServers = new HashSet<>(asList(new ServerConfImpl("reference3", "8082", "https"), + new ServerConfImpl("reference4", "8083", "sftp"))); + expectedExposedPorts.addAll(devServers.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, @@ -501,27 +508,24 @@ public void shouldAddCommonAndDevLabelsToContainerOnDevInstanceCreationFromSnaps ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getLabels(), expectedLabels); + + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldAddOnlyCommonLabelsToContainerOnNonDevInstanceCreationFromSnapshot() throws Exception { - final Map expectedLabels = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedLabels.put("che:server:" + server.getPort() + ":ref", server.getRef()); - expectedLabels.put("che:server:" + server.getPort() + ":protocol", server.getProtocol()); - } - - final Set devServers = new HashSet<>(asList(new ServerConf("reference3", "8082", "https"), - new ServerConf("reference4", "8083", "sftp"))); + public void shouldExposeOnlyCommonPortsToContainerOnNonDevInstanceCreationFromSnapshot() throws Exception { + List expectedExposedPorts = new ArrayList<>(); + final Set commonServers = new HashSet<>(asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp"))); + expectedExposedPorts.addAll(commonServers.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, dockerMachineFactory, dockerInstanceStopDetector, - devServers, + Collections.emptySet(), commonServers, Collections.emptySet(), Collections.emptySet(), @@ -540,30 +544,26 @@ public void shouldAddOnlyCommonLabelsToContainerOnNonDevInstanceCreationFromSnap ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getLabels(), expectedLabels); + + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldExposeCommonAndDevPortsToContainerOnDevInstanceCreationFromRecipe() throws Exception { - Map> expectedExposedPorts = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedExposedPorts.put(server.getPort(), Collections.emptyMap()); - } - - final Set devServers = new HashSet<>(asList(new ServerConf("reference3", "8082", "https"), - new ServerConf("reference4", "8083", "sftp"))); - for (ServerConf server : devServers) { - expectedExposedPorts.put(server.getPort(), Collections.emptyMap()); - } + public void shouldAddServersConfsPortsFromMachineConfigToExposedPortsOnNonDevInstanceCreationFromSnapshot() throws Exception { + // given + List expectedExposedPorts = new ArrayList<>(); + final List serversFromConf = asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp")); + expectedExposedPorts.addAll(serversFromConf.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, dockerMachineFactory, dockerInstanceStopDetector, - devServers, - commonServers, + Collections.emptySet(), + Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), null, @@ -573,33 +573,37 @@ public void shouldExposeCommonAndDevPortsToContainerOnDevInstanceCreationFromRec Collections.emptySet(), Collections.emptySet()); - final boolean isDev = true; - - - createInstanceFromRecipe(isDev); + final boolean isDev = false; + // when + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setServers(serversFromConf) + .build()) + .build()); + // then ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getExposedPorts(), expectedExposedPorts); + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldExposeOnlyCommonPortsToContainerOnNonDevInstanceCreationFromRecipe() throws Exception { - Map> expectedExposedPorts = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedExposedPorts.put(server.getPort(), Collections.emptyMap()); - } + public void shouldAddServersConfsPortsFromMachineConfigToExposedPortsOnNonDevInstanceCreationFromRecipe() throws Exception { + // given + List expectedExposedPorts = new ArrayList<>(); + final List serversFromConf = asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp")); + expectedExposedPorts.addAll(serversFromConf.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, dockerMachineFactory, dockerInstanceStopDetector, Collections.emptySet(), - commonServers, + Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), null, @@ -611,37 +615,35 @@ public void shouldExposeOnlyCommonPortsToContainerOnNonDevInstanceCreationFromRe final boolean isDev = false; + // when + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setServers(serversFromConf) + .build()) + .build()); - createInstanceFromRecipe(isDev); - - + // then ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getExposedPorts(), expectedExposedPorts); + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldExposeCommonAndDevPortsToContainerOnDevInstanceCreationFromSnapshot() throws Exception { - Map> expectedExposedPorts = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedExposedPorts.put(server.getPort(), Collections.emptyMap()); - } - - final Set devServers = new HashSet<>(asList(new ServerConf("reference3", "8082", "https"), - new ServerConf("reference4", "8083", "sftp"))); - for (ServerConf server : devServers) { - expectedExposedPorts.put(server.getPort(), Collections.emptyMap()); - } + public void shouldAddServersConfsPortsFromMachineConfigToExposedPortsOnDevInstanceCreationFromSnapshot() throws Exception { + // given + List expectedExposedPorts = new ArrayList<>(); + final List serversFromConf = asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp")); + expectedExposedPorts.addAll(serversFromConf.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, dockerMachineFactory, dockerInstanceStopDetector, - devServers, - commonServers, + Collections.emptySet(), + Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), null, @@ -653,31 +655,35 @@ public void shouldExposeCommonAndDevPortsToContainerOnDevInstanceCreationFromSna final boolean isDev = true; + // when + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setServers(serversFromConf) + .build()) + .build()); - createInstanceFromSnapshot(isDev); - - + // then ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getExposedPorts(), expectedExposedPorts); + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test - public void shouldExposeOnlyCommonPortsToContainerOnNonDevInstanceCreationFromSnapshot() throws Exception { - Map> expectedExposedPorts = new HashMap<>(); - final Set commonServers = new HashSet<>(asList(new ServerConf("reference1", "8080", "http"), - new ServerConf("reference2", "8081", "ftp"))); - for (ServerConf server : commonServers) { - expectedExposedPorts.put(server.getPort(), Collections.emptyMap()); - } + public void shouldAddServersConfsPortsFromMachineConfigToExposedPortsOnDevInstanceCreationFromRecipe() throws Exception { + // given + List expectedExposedPorts = new ArrayList<>(); + final List serversFromConf = asList(new ServerConfImpl("reference1", "8080", "http"), + new ServerConfImpl("reference2", "8081", "ftp")); + expectedExposedPorts.addAll(serversFromConf.stream() + .map(ServerConf::getPort) + .collect(Collectors.toList())); dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, dockerMachineFactory, dockerInstanceStopDetector, Collections.emptySet(), - commonServers, + Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), null, @@ -687,22 +693,25 @@ public void shouldExposeOnlyCommonPortsToContainerOnNonDevInstanceCreationFromSn Collections.emptySet(), Collections.emptySet()); - final boolean isDev = false; - - - createInstanceFromSnapshot(isDev); + final boolean isDev = true; + // when + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setServers(serversFromConf) + .build()) + .build()); + // then ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(argumentCaptor.getValue().getExposedPorts(), expectedExposedPorts); + assertTrue(new ArrayList<>(argumentCaptor.getValue().getExposedPorts().keySet()).containsAll(expectedExposedPorts)); } @Test public void shouldBindProjectsFSVolumeToContainerOnDevInstanceCreationFromRecipe() throws Exception { final String expectedHostPathOfProjects = "/tmp/projects"; - String[] expectedVolumes = new String[]{expectedHostPathOfProjects + ":/projects"}; + String[] expectedVolumes = new String[] {expectedHostPathOfProjects + ":/projects"}; dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, @@ -737,7 +746,7 @@ public void shouldBindProjectsFSVolumeToContainerOnDevInstanceCreationFromRecipe @Test public void shouldBindProjectsFSVolumeToContainerOnDevInstanceCreationFromSnapshot() throws Exception { final String expectedHostPathOfProjects = "/tmp/projects"; - final String[] expectedVolumes = new String[]{expectedHostPathOfProjects + ":/projects"}; + final String[] expectedVolumes = new String[] {expectedHostPathOfProjects + ":/projects"}; dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, dockerConnectorConfiguration, @@ -1176,7 +1185,7 @@ public void shouldGenerateValidNameForContainerFromPrefixWithValidCharacters() t public void shouldGenerateValidNameForContainerFromPrefixWithInvalidCharacters() throws Exception { final String userName = "{use}r+"; final String displayName = "displ{[ayName@"; - EnvironmentContext.getCurrent().setUser(new UserImpl(userName)); + EnvironmentContext.getCurrent().setUser(new UserImpl(userName, "id", "token", emptyList(), false)); final String expectedPrefix = String.format("%s_%s_%s_", "user", "WORKSPACE_ID", "displayName"); final String containerName = dockerInstanceProvider.generateContainerName("WORKSPACE_ID", displayName); @@ -1191,8 +1200,8 @@ public void shouldAddWorkspaceIdEnvVariableOnDevInstanceCreationFromRecipe() thr createInstanceFromRecipe(true, wsId); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertTrue(Arrays.asList(argumentCaptor.getValue().getEnv()) - .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), + assertTrue(asList(argumentCaptor.getValue().getEnv()) + .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), "Workspace Id variable is missing. Required " + DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId + ". Found " + Arrays.toString(argumentCaptor.getValue().getEnv())); } @@ -1203,8 +1212,8 @@ public void shouldAddWorkspaceIdEnvVariableOnDevInstanceCreationFromSnapshot() t createInstanceFromSnapshot(true, wsId); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertTrue(Arrays.asList(argumentCaptor.getValue().getEnv()) - .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), + assertTrue(asList(argumentCaptor.getValue().getEnv()) + .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), "Workspace Id variable is missing. Required " + DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId + ". Found " + Arrays.toString(argumentCaptor.getValue().getEnv())); } @@ -1215,8 +1224,8 @@ public void shouldNotAddWorkspaceIdEnvVariableOnNonDevInstanceCreationFromRecipe createInstanceFromRecipe(false, wsId); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertFalse(Arrays.asList(argumentCaptor.getValue().getEnv()) - .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), + assertFalse(asList(argumentCaptor.getValue().getEnv()) + .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), "Non dev machine should not contains " + DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID); } @@ -1226,19 +1235,19 @@ public void shouldNotAddWorkspaceIdEnvVariableOnNonDevInstanceCreationFromSnapsh createInstanceFromSnapshot(false, wsId); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertFalse(Arrays.asList(argumentCaptor.getValue().getEnv()) - .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), + assertFalse(asList(argumentCaptor.getValue().getEnv()) + .contains(DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID + "=" + wsId), "Non dev machine should not contains " + DockerInstanceRuntimeInfo.CHE_WORKSPACE_ID); } /** * E.g from https://github.com/boot2docker/boot2docker/blob/master/README.md#virtualbox-guest-additions * - * Users should be /Users - * /Users should be /Users - * c/Users should be /c/Users - * /c/Users should be /c/Users - * c:/Users should be /c/Users + * Users should be /Users + * /Users should be /Users + * c/Users should be /c/Users + * /c/Users should be /c/Users + * c:/Users should be /c/Users */ @Test public void shouldEscapePathForWindowsHost() { @@ -1286,7 +1295,7 @@ public void shouldAddCommonAndDevEnvVariablesToContainerOnDevInstanceCreationFro ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(new HashSet<>(Arrays.asList(argumentCaptor.getValue().getEnv())), expectedEnv); + assertTrue(new HashSet<>(asList(argumentCaptor.getValue().getEnv())).containsAll(expectedEnv)); } @Test @@ -1317,7 +1326,7 @@ public void shouldNotAddDevEnvToCommonEnvVariablesToContainerOnNonDevInstanceCre ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(new HashSet<>(Arrays.asList(argumentCaptor.getValue().getEnv())), commonEnv); + assertTrue(new HashSet<>(asList(argumentCaptor.getValue().getEnv())).containsAll(commonEnv)); } @Test @@ -1353,7 +1362,7 @@ public void shouldAddCommonAndDevEnvVariablesToContainerOnDevInstanceCreationFro ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(new HashSet<>(Arrays.asList(argumentCaptor.getValue().getEnv())), expectedEnv); + assertTrue(new HashSet<>(asList(argumentCaptor.getValue().getEnv())).containsAll(expectedEnv)); } @Test @@ -1384,171 +1393,271 @@ public void shouldNotAddDevEnvToCommonEnvVariablesToContainerOnNonDevInstanceCre ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); - assertEquals(new HashSet<>(Arrays.asList(argumentCaptor.getValue().getEnv())), commonEnv); + assertTrue(new HashSet<>(asList(argumentCaptor.getValue().getEnv())).containsAll(commonEnv)); + } + + @Test + public void shouldAddEnvVarsFromMachineConfigToContainerOnNonDevInstanceCreationFromSnapshot() throws Exception { + // given + Map envVarsFromConfig = new HashMap<>(); + envVarsFromConfig.put("ENV_VAR1", "123"); + envVarsFromConfig.put("ENV_VAR2", "234"); + + dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, + dockerConnectorConfiguration, + dockerMachineFactory, + dockerInstanceStopDetector, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + null, + workspaceFolderPathProvider, + PROJECT_FOLDER_PATH, + false, + Collections.emptySet(), + Collections.emptySet()); + + final boolean isDev = false; + + // when + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setEnvVariables(envVarsFromConfig) + .build()) + .build()); + + // then + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); + verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); + assertTrue(asList(argumentCaptor.getValue().getEnv()).containsAll(envVarsFromConfig.entrySet() + .stream() + .map(entry -> entry.getKey() + + "=" + + entry.getValue()) + .collect(Collectors.toList()))); + } + + @Test + public void shouldAddEnvVarsFromMachineConfigToContainerOnDevInstanceCreationFromSnapshot() throws Exception { + // given + Map envVarsFromConfig = new HashMap<>(); + envVarsFromConfig.put("ENV_VAR1", "123"); + envVarsFromConfig.put("ENV_VAR2", "234"); + + dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, + dockerConnectorConfiguration, + dockerMachineFactory, + dockerInstanceStopDetector, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + null, + workspaceFolderPathProvider, + PROJECT_FOLDER_PATH, + false, + Collections.emptySet(), + Collections.emptySet()); + + final boolean isDev = true; + + // when + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setEnvVariables(envVarsFromConfig) + .build()) + .build()); + + // then + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); + verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); + assertTrue(asList(argumentCaptor.getValue().getEnv()).containsAll(envVarsFromConfig.entrySet() + .stream() + .map(entry -> entry.getKey() + + "=" + + entry.getValue()) + .collect(Collectors.toList()))); + } + + @Test + public void shouldAddEnvVarsFromMachineConfigToContainerOnNonDevInstanceCreationFromRecipe() throws Exception { + // given + Map envVarsFromConfig = new HashMap<>(); + envVarsFromConfig.put("ENV_VAR1", "123"); + envVarsFromConfig.put("ENV_VAR2", "234"); + + dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, + dockerConnectorConfiguration, + dockerMachineFactory, + dockerInstanceStopDetector, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + null, + workspaceFolderPathProvider, + PROJECT_FOLDER_PATH, + false, + Collections.emptySet(), + Collections.emptySet()); + + final boolean isDev = false; + + // when + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setEnvVariables(envVarsFromConfig) + .build()) + .build()); + + // then + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); + verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); + assertTrue(asList(argumentCaptor.getValue().getEnv()).containsAll(envVarsFromConfig.entrySet() + .stream() + .map(entry -> entry.getKey() + + "=" + + entry.getValue()) + .collect(Collectors.toList()))); + } + + @Test + public void shouldAddEnvVarsFromMachineConfigToContainerOnDevInstanceCreationFromRecipe() throws Exception { + // given + Map envVarsFromConfig = new HashMap<>(); + envVarsFromConfig.put("ENV_VAR1", "123"); + envVarsFromConfig.put("ENV_VAR2", "234"); + + dockerInstanceProvider = new DockerInstanceProvider(dockerConnector, + dockerConnectorConfiguration, + dockerMachineFactory, + dockerInstanceStopDetector, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + null, + workspaceFolderPathProvider, + PROJECT_FOLDER_PATH, + false, + Collections.emptySet(), + Collections.emptySet()); + + final boolean isDev = true; + + // when + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .setEnvVariables(envVarsFromConfig) + .build()) + .build()); + + // then + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ContainerConfig.class); + verify(dockerConnector).createContainer(argumentCaptor.capture(), anyString()); + assertTrue(asList(argumentCaptor.getValue().getEnv()).containsAll(envVarsFromConfig.entrySet() + .stream() + .map(entry -> entry.getKey() + + "=" + + entry.getValue()) + .collect(Collectors.toList()))); } private void createInstanceFromRecipe() throws Exception { - createInstanceFromRecipe(false, - MEMORY_LIMIT_MB, - "machineId", - "userId", - WORKSPACE_ID, - DISPLAY_NAME, - new RecipeImpl().withType("Dockerfile") - .withScript("FROM busybox")); + createInstanceFromRecipe(getMachineBuilder().build()); } private void createInstanceFromRecipe(boolean isDev) throws Exception { - createInstanceFromRecipe(isDev, null, null, null, null, null, null); + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .build()) + .build()); } private void createInstanceFromRecipe(boolean isDev, String workspaceId) throws Exception { - createInstanceFromRecipe(isDev, null, null, null, workspaceId, null, null); + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .build()) + .setWorkspaceId(workspaceId) + .build()); } private void createInstanceFromRecipe(int memorySizeInMB) throws Exception { - createInstanceFromRecipe(null, memorySizeInMB, null, null, null, null, null); - } - - private void createInstanceFromRecipe(Boolean isDev, - Integer memorySizeInMB, - String machineId, - String userId, - String workspaceId, - String displayName, - Recipe recipe) throws Exception { - - createInstanceFromRecipe(isDev == null ? false : isDev, - memorySizeInMB == null ? MEMORY_LIMIT_MB : memorySizeInMB, - machineId == null ? "machineId" : machineId, - userId == null ? "userId" : userId, - workspaceId == null ? WORKSPACE_ID : workspaceId, - displayName == null ? DISPLAY_NAME : displayName, - recipe == null ? new RecipeImpl().withType("Dockerfile") - .withScript("FROM busybox") : recipe, - "machineType", - new MachineSourceImpl("source type", "source location"), - MachineStatus.CREATING); - } - - private void createInstanceFromRecipe(boolean isDev, - int memorySizeInMB, - String machineId, - String userId, - String workspaceId, - String displayName, - Recipe recipe, - String machineType, - MachineSource machineSource, - MachineStatus machineStatus) - throws Exception { - - dockerInstanceProvider.createInstance(recipe, - new MachineImpl(new MachineConfigImpl(isDev, - displayName, - machineType, - machineSource, - new LimitsImpl(memorySizeInMB)), - machineId, - workspaceId, - "envName", - userId, - machineStatus, - null), - LineConsumer.DEV_NULL); + createInstanceFromRecipe(getMachineBuilder().setConfig(getMachineConfigBuilder().setLimits(new LimitsImpl(memorySizeInMB)) + .build()) + .build()); } - private void createInstanceFromRecipe(Recipe recipe, Machine machine) throws Exception { + private void createInstanceFromSnapshot(String repo, String tag, String registry) throws NotFoundException, MachineException { + createInstanceFromSnapshot(getMachineBuilder().build(), new DockerInstanceKey(repo, tag, "imageId", registry)); + } - dockerInstanceProvider.createInstance(recipe, + private void createInstanceFromRecipe(Machine machine) throws Exception { + dockerInstanceProvider.createInstance(new RecipeImpl().withType("Dockerfile") + .withScript("FROM busybox"), machine, LineConsumer.DEV_NULL); } private void createInstanceFromSnapshot() throws NotFoundException, MachineException { - createInstanceFromSnapshot(null, null, null, null, null, null, null, null, null); + createInstanceFromSnapshot(getMachineBuilder().build()); } private void createInstanceFromSnapshot(int memorySizeInMB) throws NotFoundException, MachineException { - createInstanceFromSnapshot(null, null, null, null, memorySizeInMB, null, null, null, null); + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setLimits(new LimitsImpl(memorySizeInMB)) + .build()) + .build()); } private void createInstanceFromSnapshot(boolean isDev) throws NotFoundException, MachineException { - createInstanceFromSnapshot(null, null, null, isDev, null, null, null, null, null); + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .build()) + .build()); } private void createInstanceFromSnapshot(boolean isDev, String workspaceId) throws NotFoundException, MachineException { - createInstanceFromSnapshot(null, null, null, isDev, null, null, null, workspaceId, null); + createInstanceFromSnapshot(getMachineBuilder().setConfig(getMachineConfigBuilder().setDev(isDev) + .build()) + .setWorkspaceId(workspaceId) + .build()); } - private void createInstanceFromSnapshot(String repo, String tag, String registry) throws NotFoundException, MachineException { - createInstanceFromSnapshot(repo, tag, registry, null, null, null, null, null, null); - } - - private void createInstanceFromSnapshot(String repo, - String tag, - String registry, - Boolean isDev, - Integer memorySizeInMB, - String machineId, - String userId, - String workspaceId, - String displayName) - throws NotFoundException, MachineException { - - createInstanceFromSnapshot(repo == null ? "repo" : repo, - tag == null ? "tag" : tag, - registry == null ? "localhost:1234" : registry, - isDev == null ? false : isDev, - memorySizeInMB == null ? MEMORY_LIMIT_MB : memorySizeInMB, - machineId == null ? "machineId" : machineId, - userId == null ? "userId" : userId, - workspaceId == null ? WORKSPACE_ID : workspaceId, - displayName == null ? DISPLAY_NAME : displayName, - "machineType", - new MachineSourceImpl("source type", "source location"), - MachineStatus.CREATING, - "envName"); - } - - private void createInstanceFromSnapshot(String repo, - String tag, - String registry, - boolean isDev, - int memorySizeInMB, - String machineId, - String userId, - String workspaceId, - String displayName, - String machineType, - MachineSource machineSource, - MachineStatus machineStatus, - String envName) - throws NotFoundException, MachineException { - - dockerInstanceProvider.createInstance(new DockerInstanceKey(repo, tag, "imageId", registry), - new MachineImpl(new MachineConfigImpl(isDev, - displayName, - machineType, - machineSource, - new LimitsImpl(memorySizeInMB)), - machineId, - workspaceId, - envName, - userId, - machineStatus, - null), + private void createInstanceFromRecipe(Recipe recipe, Machine machine) throws Exception { + dockerInstanceProvider.createInstance(recipe, + machine, LineConsumer.DEV_NULL); } - private void createInstanceFromSnapshot(Machine machine) - throws NotFoundException, MachineException { - - dockerInstanceProvider.createInstance(new DockerInstanceKey("repo" , + private void createInstanceFromSnapshot(Machine machine) throws NotFoundException, MachineException { + dockerInstanceProvider.createInstance(new DockerInstanceKey("repo", "tag", "imageId", "localhost:1234"), machine, LineConsumer.DEV_NULL); } -} \ No newline at end of file + + private void createInstanceFromSnapshot(Machine machine, DockerInstanceKey dockerInstanceKey) throws NotFoundException, + MachineException { + dockerInstanceProvider.createInstance(dockerInstanceKey, + machine, + LineConsumer.DEV_NULL); + } + + private MachineImpl.MachineImplBuilder getMachineBuilder() { + return MachineImpl.builder().fromMachine(new MachineImpl(getMachineConfigBuilder().build(), + "machineId", + WORKSPACE_ID, + "envName", + "userId", + MachineStatus.CREATING, + null)); + } + + private MachineConfigImpl.MachineConfigImplBuilder getMachineConfigBuilder() { + return MachineConfigImpl.builder().fromConfig(new MachineConfigImpl(false, + DISPLAY_NAME, + "machineType", + new MachineSourceImpl("source type", "source location"), + new LimitsImpl(MEMORY_LIMIT_MB), + asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", + "someprotocol")), + Collections.singletonMap("key1", "value1"))); + } +} diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceReadFileContentTest.java b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceReadFileContentTest.java index b0a12019178..d38703f7c74 100644 --- a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceReadFileContentTest.java +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceReadFileContentTest.java @@ -17,6 +17,7 @@ import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl; import org.eclipse.che.api.machine.server.model.impl.MachineImpl; import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; import org.eclipse.che.plugin.docker.client.DockerConnector; import org.eclipse.che.plugin.docker.client.Exec; import org.eclipse.che.plugin.docker.client.LogMessage; @@ -29,7 +30,9 @@ import org.testng.annotations.Test; import java.io.IOException; +import java.util.Collections; +import static java.util.Arrays.asList; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyString; @@ -63,11 +66,16 @@ public void setUp() throws IOException { dockerInstance = spy(new DockerInstance(dockerConnector, null, null, - new MachineImpl(new MachineConfigImpl(false, - "Display name", - "machineType", - new MachineSourceImpl("type", "location"), - new LimitsImpl(64)), + new MachineImpl( + new MachineConfigImpl(false, + "Display name", + "machineType", + new MachineSourceImpl("type", "location"), + new LimitsImpl(64), + asList(new ServerConfImpl("ref1", "8080", "https"), + new ServerConfImpl("ref2", "9090/udp", + "someprotocol")), + Collections.singletonMap("key1", "value1")), "machineId", "workspaceId", "envName", @@ -144,4 +152,4 @@ public void readFileContentTest() throws MachineException, ConflictException, IO assertEquals(result.trim(), content); } -} \ No newline at end of file +} diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfoTest.java b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfoTest.java new file mode 100644 index 00000000000..853609b8d0c --- /dev/null +++ b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/DockerInstanceRuntimeInfoTest.java @@ -0,0 +1,471 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.plugin.docker.machine; + +import org.eclipse.che.api.core.model.machine.MachineConfig; +import org.eclipse.che.api.core.model.machine.ServerConf; +import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl; +import org.eclipse.che.api.machine.server.model.impl.ServerImpl; +import org.eclipse.che.plugin.docker.client.json.ContainerConfig; +import org.eclipse.che.plugin.docker.client.json.ContainerInfo; +import org.eclipse.che.plugin.docker.client.json.NetworkSettings; +import org.eclipse.che.plugin.docker.client.json.PortBinding; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo.SERVER_CONF_LABEL_PREFIX; +import static org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo.SERVER_CONF_LABEL_PROTOCOL_SUFFIX; +import static org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo.SERVER_CONF_LABEL_REF_SUFFIX; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; + +@Listeners(MockitoTestNGListener.class) +public class DockerInstanceRuntimeInfoTest { + private static final String CONTAINER_HOST = "container-host.com"; + private static final String DEFAULT_ADDRESS = "192.168.1.1"; + + @Mock + private ContainerInfo containerInfo; + @Mock + private MachineConfig machineConfig; + @Mock + private ContainerConfig containerConfig; + @Mock + private NetworkSettings networkSettings; + + private DockerInstanceRuntimeInfo runtimeInfo; + + @BeforeMethod + public void setUp() { + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + Collections.emptySet(), + Collections.emptySet()); + + when(containerInfo.getConfig()).thenReturn(containerConfig); + when(containerInfo.getNetworkSettings()).thenReturn(networkSettings); + when(machineConfig.getServers()).thenReturn(Collections.emptyList()); + when(containerConfig.getLabels()).thenReturn(Collections.emptyMap()); + } + + @Test + public void shouldReturnEnvVars() throws Exception { + // given + Map expectedVariables = new HashMap<>(); + expectedVariables.put("env_var1", "value1"); + expectedVariables.put("env_var2", "value2"); + expectedVariables.put("env_var3", "value3"); + + when(containerConfig.getEnv()).thenReturn(expectedVariables.entrySet() + .stream() + .map(stringStringEntry -> stringStringEntry.getKey() + + "=" + + stringStringEntry.getValue()) + .collect(Collectors.toList()) + .toArray(new String[expectedVariables.size()])); + + // when + final Map envVariables = runtimeInfo.getEnvVariables(); + + // then + assertEquals(envVariables, expectedVariables); + } + + @Test + public void shouldReturnEmptyMapIfNoEnvVariablesFound() throws Exception { + when(containerConfig.getEnv()).thenReturn(new String[0]); + + assertEquals(runtimeInfo.getEnvVariables(), Collections.emptyMap()); + } + + @Test + public void shouldReturnProjectsRoot() throws Exception { + final String projectsRoot = "/testProjectRoot"; + final String[] envVars = { + "var1=value1", + "var2=value2", + DockerInstanceRuntimeInfo.PROJECTS_ROOT_VARIABLE + "=" + projectsRoot, + "var3=value3" + }; + when(containerConfig.getEnv()).thenReturn(envVars); + + assertEquals(runtimeInfo.projectsRoot(), projectsRoot); + } + + @Test + public void shouldReturnNullProjectsRootIfNoAppropriateEnvVarFound() throws Exception { + final String[] envVars = { + "var1=value1", + "var2=value2", + "var3=value3" + }; + when(containerConfig.getEnv()).thenReturn(envVars); + + assertEquals(runtimeInfo.projectsRoot(), null); + } + + @Test + public void shouldReturnServerForEveryExposedPort() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("100100/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.keySet(), ports.keySet()); + } + + @Test + public void shouldAddDefaultReferenceIfReferenceIsNotSet() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("100100/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("8080/tcp"), new ServerImpl("Server-8080-tcp", + CONTAINER_HOST + ":32100", + null)); + assertEquals(servers.get("100100/udp"), new ServerImpl("Server-100100-udp", + CONTAINER_HOST + ":32101", + null)); + assertEquals(servers.get("8080/udp"), new ServerImpl("Server-8080-udp", + CONTAINER_HOST + ":32102", + null)); + } + + @Test + public void shouldAddRefAndUrlToServerFromMachineConfig() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + List serversConfigs = new ArrayList<>(); + doReturn(serversConfigs).when(machineConfig).getServers(); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("100100/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + ports.put("8000/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32103"))); + serversConfigs.add(new ServerConfImpl("myserv1", "8080/tcp", "http")); + serversConfigs.add(new ServerConfImpl("myserv1-tftp", "8080/udp", "tftp")); + serversConfigs.add(new ServerConfImpl("myserv2", "100100/udp", "dhcp")); + serversConfigs.add(new ServerConfImpl(null, "8000/tcp", "tcp")); + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + Collections.emptySet(), + Collections.emptySet()); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("8080/tcp"), new ServerImpl("myserv1", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("100100/udp"), new ServerImpl("myserv2", + CONTAINER_HOST + ":32101", + "dhcp://" + CONTAINER_HOST + ":32101")); + assertEquals(servers.get("8080/udp"), new ServerImpl("myserv1-tftp", + CONTAINER_HOST + ":32102", + "tftp://" + CONTAINER_HOST + ":32102")); + assertEquals(servers.get("8000/tcp"), new ServerImpl("Server-8000-tcp", + CONTAINER_HOST + ":32103", + "tcp://" + CONTAINER_HOST + ":32103")); + } + + @Test + public void shouldAllowToUsePortFromMachineConfigWithoutTransportProtocol() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + List serversConfigs = new ArrayList<>(); + doReturn(serversConfigs).when(machineConfig).getServers(); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + serversConfigs.add(new ServerConfImpl("myserv1", "8080", "http")); + serversConfigs.add(new ServerConfImpl("myserv1-tftp", "8080/udp", "tftp")); + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + Collections.emptySet(), + Collections.emptySet()); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("8080/tcp"), new ServerImpl("myserv1", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("8080/udp"), new ServerImpl("myserv1-tftp", + CONTAINER_HOST + ":32102", + "tftp://" + CONTAINER_HOST + ":32102")); + } + + @Test + public void shouldAddRefAndUrlToServerFromLabels() throws Exception { + // given + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + Collections.emptySet(), + Collections.emptySet()); + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + Map labels = new HashMap<>(); + when(containerConfig.getLabels()).thenReturn(labels); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("100100/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + ports.put("8000/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32103"))); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/tcp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv1"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/tcp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "http"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/udp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv1-tftp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/udp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "tftp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "100100/udp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv2"); + labels.put(SERVER_CONF_LABEL_PREFIX + "100100/udp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "dhcp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8000/tcp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "tcp"); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("8080/tcp"), new ServerImpl("myserv1", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("100100/udp"), new ServerImpl("myserv2", + CONTAINER_HOST + ":32101", + "dhcp://" + CONTAINER_HOST + ":32101")); + assertEquals(servers.get("8080/udp"), new ServerImpl("myserv1-tftp", + CONTAINER_HOST + ":32102", + "tftp://" + CONTAINER_HOST + ":32102")); + assertEquals(servers.get("8000/tcp"), new ServerImpl("Server-8000-tcp", + CONTAINER_HOST + ":32103", + "tcp://" + CONTAINER_HOST + ":32103")); + } + + @Test + public void shouldAllowToUsePortFromDockerLabelsWithoutTransportProtocol() throws Exception { + // given + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + Collections.emptySet(), + Collections.emptySet()); + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + Map labels = new HashMap<>(); + when(containerConfig.getLabels()).thenReturn(labels); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + ports.put("8000/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32103"))); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv1"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "http"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/udp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv1-tftp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/udp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "tftp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8000" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv2"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8000/tcp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "tcp"); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("8080/tcp"), new ServerImpl("myserv1", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("8080/udp"), new ServerImpl("myserv1-tftp", + CONTAINER_HOST + ":32102", + "tftp://" + CONTAINER_HOST + ":32102")); + assertEquals(servers.get("8000/tcp"), new ServerImpl("myserv2", + CONTAINER_HOST + ":32103", + "tcp://" + CONTAINER_HOST + ":32103")); + } + + @Test + public void shouldPreferMachineConfOverDockerLabels() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + Map labels = new HashMap<>(); + when(containerConfig.getLabels()).thenReturn(labels); + List serversConfigs = new ArrayList<>(); + doReturn(serversConfigs).when(machineConfig).getServers(); + ports.put("8080/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("100100/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("8080/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + ports.put("8000/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32103"))); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/tcp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv1label"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/tcp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "https"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/udp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv1-tftp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "8080/udp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "tftp"); + labels.put(SERVER_CONF_LABEL_PREFIX + "100100/udp" + SERVER_CONF_LABEL_REF_SUFFIX, "myserv2label"); + labels.put(SERVER_CONF_LABEL_PREFIX + "100100/udp" + SERVER_CONF_LABEL_PROTOCOL_SUFFIX, "dhcp"); + serversConfigs.add(new ServerConfImpl("myserv1conf", "8080/tcp", "http")); + serversConfigs.add(new ServerConfImpl(null, "8080/udp", null)); + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + Collections.emptySet(), + Collections.emptySet()); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("8080/tcp"), new ServerImpl("myserv1conf", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("100100/udp"), new ServerImpl("myserv2label", + CONTAINER_HOST + ":32101", + "dhcp://" + CONTAINER_HOST + ":32101")); + assertEquals(servers.get("8080/udp"), new ServerImpl("Server-8080-udp", + CONTAINER_HOST + ":32102", + null)); + } + + @Test + public void shouldAddOnlyCommonSystemServersConfigToNonDevMachine() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + ports.put("4301/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("4302/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("4301/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + // add user defined server + ports.put("4305/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32103"))); + Set commonSystemServersConfigs = new HashSet<>(); + commonSystemServersConfigs.add(new ServerConfImpl("sysServer1-tcp", "4301/tcp", "http")); + commonSystemServersConfigs.add(new ServerConfImpl("sysServer2-udp", "4302/udp", "dhcp")); + commonSystemServersConfigs.add(new ServerConfImpl("sysServer1-udp", "4301/udp", null)); + Set devSystemServersConfigs = new HashSet<>(); + devSystemServersConfigs.add(new ServerConfImpl("devSysServer1-tcp", "4305/tcp", "http")); + when(machineConfig.isDev()).thenReturn(false); + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + devSystemServersConfigs, + commonSystemServersConfigs); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("4301/tcp"), new ServerImpl("sysServer1-tcp", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("4302/udp"), new ServerImpl("sysServer2-udp", + CONTAINER_HOST + ":32101", + "dhcp://" + CONTAINER_HOST + ":32101")); + assertEquals(servers.get("4301/udp"), new ServerImpl("sysServer1-udp", + CONTAINER_HOST + ":32102", + null)); + assertEquals(servers.get("4305/tcp"), new ServerImpl("Server-4305-tcp", + CONTAINER_HOST + ":32103", + null)); + } + + @Test + public void shouldAddCommonAndDevSystemServersConfigToDevMachine() throws Exception { + // given + Map> ports = new HashMap<>(); + when(networkSettings.getPorts()).thenReturn(ports); + ports.put("4301/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32100"))); + ports.put("4302/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32101"))); + ports.put("4305/tcp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32102"))); + ports.put("4305/udp", Collections.singletonList(new PortBinding().withHostIp(DEFAULT_ADDRESS) + .withHostPort("32103"))); + Set commonSystemServersConfigs = new HashSet<>(); + commonSystemServersConfigs.add(new ServerConfImpl("sysServer1-tcp", "4301/tcp", "http")); + commonSystemServersConfigs.add(new ServerConfImpl("sysServer2-udp", "4302/udp", "dhcp")); + Set devSystemServersConfigs = new HashSet<>(); + devSystemServersConfigs.add(new ServerConfImpl("devSysServer1-tcp", "4305/tcp", "http")); + devSystemServersConfigs.add(new ServerConfImpl("devSysServer1-udp", "4305/udp", null)); + when(machineConfig.isDev()).thenReturn(true); + runtimeInfo = new DockerInstanceRuntimeInfo(containerInfo, + CONTAINER_HOST, + machineConfig, + devSystemServersConfigs, + commonSystemServersConfigs); + + // when + final Map servers = runtimeInfo.getServers(); + + // then + assertEquals(servers.get("4301/tcp"), new ServerImpl("sysServer1-tcp", + CONTAINER_HOST + ":32100", + "http://" + CONTAINER_HOST + ":32100")); + assertEquals(servers.get("4302/udp"), new ServerImpl("sysServer2-udp", + CONTAINER_HOST + ":32101", + "dhcp://" + CONTAINER_HOST + ":32101")); + assertEquals(servers.get("4305/tcp"), new ServerImpl("devSysServer1-tcp", + CONTAINER_HOST + ":32102", + "http://" + CONTAINER_HOST + ":32102")); + assertEquals(servers.get("4305/udp"), new ServerImpl("devSysServer1-udp", + CONTAINER_HOST + ":32103", + null)); + } + + +} diff --git a/plugins/plugin-java/che-plugin-java-ext-debugger-java-client/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/remotedebug/RemoteDebugPresenter.java b/plugins/plugin-java/che-plugin-java-ext-debugger-java-client/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/remotedebug/RemoteDebugPresenter.java index 7afcd9afea8..b86d7ce2f5c 100644 --- a/plugins/plugin-java/che-plugin-java-ext-debugger-java-client/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/remotedebug/RemoteDebugPresenter.java +++ b/plugins/plugin-java/che-plugin-java-ext-debugger-java-client/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/remotedebug/RemoteDebugPresenter.java @@ -88,11 +88,13 @@ public void apply(MachineDto machineDto) throws OperationException { private List> extractPortsList(Machine machine) { List> ports = new ArrayList>(); for (Server server : machine.getServersList()) { - String description = server.getPort() + " (" + server.getRef() + ")"; - String value = server.getPort(); - Pair pair = new Pair<>(description, value); + if (server.getPort().endsWith("/tcp")) { + String portWithoutTcp = server.getPort().substring(0, server.getPort().length() - 4); + String description = portWithoutTcp + " (" + server.getRef() + ")"; + Pair pair = new Pair<>(description, portWithoutTcp); - ports.add(pair); + ports.add(pair); + } } return ports; diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/command/valueproviders/ServerPortProvider.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/command/valueproviders/ServerPortProvider.java index 2c36326c1a3..db83b27f598 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/command/valueproviders/ServerPortProvider.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/command/valueproviders/ServerPortProvider.java @@ -29,6 +29,7 @@ import org.eclipse.che.ide.api.app.AppContext; import java.util.Collection; +import java.util.HashMap; import java.util.Map; import static com.google.common.collect.Maps.transformEntries; @@ -89,8 +90,16 @@ public CommandPropertyValueProvider transformEntry(String internalPort, ServerDt }; Map providers = transformEntries(machine.getRuntime().getServers(), machineToProvider); + Map providersWithNoTcpAliases = new HashMap<>(); + for (Map.Entry providerEntry : providers.entrySet()) { + if (providerEntry.getKey().endsWith("/tcp")) { + providersWithNoTcpAliases.put(providerEntry.getKey().substring(0, providerEntry.getKey().length() - 4), + providerEntry.getValue()); + } + } + providersWithNoTcpAliases.putAll(providers); - return providers.values(); + return providersWithNoTcpAliases.values(); } @Override diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java index 674559c5742..8d190ebb9dc 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java @@ -414,8 +414,8 @@ public void onPreviewSsh(@NotNull final String machineId) { * @return ssh service address in format host:port */ private String getSshServerAddress(MachineDto machine) { - if (machine.getRuntime().getServers().containsKey(SSH_PORT)) { - return machine.getRuntime().getServers().get(SSH_PORT).getAddress(); + if (machine.getRuntime().getServers().containsKey(SSH_PORT + "/tcp")) { + return machine.getRuntime().getServers().get(SSH_PORT + "/tcp").getAddress(); } else { return null; } diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java index 18e35d67946..e77e54ab8e5 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java @@ -115,7 +115,7 @@ private SpanElement createMachineElement(final ProcessTreeNode node, final Machi MIDDLE, locale.viewNewTerminalTooltip()); - if (machine.getRuntime().getServers().containsKey(SSH_PORT)) { + if (machine.getRuntime().getServers().containsKey(SSH_PORT + "/tcp")) { SpanElement sshButton = Elements.createSpanElement(resources.getCss().sshButton()); sshButton.setTextContent("SSH"); root.appendChild(sshButton);