Rework default memory limit setting (#8422)
Extract default machine memory limit setting from InternalEnvironmentFactory to recipe specific environment factories. Make memory limit attribute optional by respecting it by resource API subsystem. Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>6.19.x
parent
21c8aaf0cf
commit
9d75f3e219
|
|
@ -21,9 +21,9 @@ import java.util.Map;
|
|||
public interface MachineConfig {
|
||||
|
||||
/**
|
||||
* Name of the attribute from {@link #getAttributes()} which if present sets memory limit of the
|
||||
* machine in bytes. If memory limit is set in environment specific recipe this attribute should
|
||||
* override value from recipe.
|
||||
* Name of the attribute from {@link #getAttributes()} which if present defines memory limit of
|
||||
* the machine in bytes. If memory limit is set in environment specific recipe this attribute used
|
||||
* in {@code MachineConfig} should override value from recipe.
|
||||
*/
|
||||
String MEMORY_LIMIT_ATTRIBUTE = "memoryLimitBytes";
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-workspace-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public class ComposeEnvironmentFactory extends InternalEnvironmentFactory<Compos
|
|||
|
||||
private final ComposeServicesStartStrategy startStrategy;
|
||||
private final ComposeEnvironmentValidator composeValidator;
|
||||
private final String defaultMachineMemorySizeAttribute;
|
||||
|
||||
@Inject
|
||||
public ComposeEnvironmentFactory(
|
||||
|
|
@ -59,9 +60,11 @@ public class ComposeEnvironmentFactory extends InternalEnvironmentFactory<Compos
|
|||
ComposeEnvironmentValidator composeValidator,
|
||||
ComposeServicesStartStrategy startStrategy,
|
||||
@Named("che.workspace.default_memory_mb") long defaultMachineMemorySizeMB) {
|
||||
super(installerRegistry, recipeRetriever, machinesValidator, defaultMachineMemorySizeMB);
|
||||
super(installerRegistry, recipeRetriever, machinesValidator);
|
||||
this.startStrategy = startStrategy;
|
||||
this.composeValidator = composeValidator;
|
||||
this.defaultMachineMemorySizeAttribute =
|
||||
String.valueOf(defaultMachineMemorySizeMB * 1024 * 1024);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -117,6 +120,8 @@ public class ComposeEnvironmentFactory extends InternalEnvironmentFactory<Compos
|
|||
final Long ramLimit = entry.getValue().getMemLimit();
|
||||
if (ramLimit != null && ramLimit > 0) {
|
||||
attributes.put(MEMORY_LIMIT_ATTRIBUTE, String.valueOf(ramLimit));
|
||||
} else {
|
||||
attributes.put(MEMORY_LIMIT_ATTRIBUTE, defaultMachineMemorySizeAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
package org.eclipse.che.workspace.infrastructure.docker.environment.dockerfile;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -33,13 +35,17 @@ import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
|
|||
public class DockerfileEnvironmentFactory
|
||||
extends InternalEnvironmentFactory<DockerfileEnvironment> {
|
||||
|
||||
private final String defaultMachineMemorySizeAttribute;
|
||||
|
||||
@Inject
|
||||
public DockerfileEnvironmentFactory(
|
||||
InstallerRegistry installerRegistry,
|
||||
RecipeRetriever recipeRetriever,
|
||||
MachineConfigsValidator machinesValidator,
|
||||
@Named("che.workspace.default_memory_mb") long defaultMachineMemorySizeMB) {
|
||||
super(installerRegistry, recipeRetriever, machinesValidator, defaultMachineMemorySizeMB);
|
||||
super(installerRegistry, recipeRetriever, machinesValidator);
|
||||
this.defaultMachineMemorySizeAttribute =
|
||||
String.valueOf(defaultMachineMemorySizeMB * 1024 * 1024);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -55,6 +61,19 @@ public class DockerfileEnvironmentFactory
|
|||
|
||||
checkArgument(dockerfile != null, "Dockerfile content should not be null.");
|
||||
|
||||
addRamLimitAttribute(machines);
|
||||
|
||||
return new DockerfileEnvironment(dockerfile, recipe, machines, warnings);
|
||||
}
|
||||
|
||||
void addRamLimitAttribute(Map<String, InternalMachineConfig> machines) {
|
||||
// sets default ram limit attribute if not present
|
||||
for (InternalMachineConfig machineConfig : machines.values()) {
|
||||
if (isNullOrEmpty(machineConfig.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE))) {
|
||||
machineConfig
|
||||
.getAttributes()
|
||||
.put(MEMORY_LIMIT_ATTRIBUTE, defaultMachineMemorySizeAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
package org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -35,13 +37,17 @@ import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
|
|||
public class DockerImageEnvironmentFactory
|
||||
extends InternalEnvironmentFactory<DockerImageEnvironment> {
|
||||
|
||||
private final String defaultMachineMemorySizeAttribute;
|
||||
|
||||
@Inject
|
||||
public DockerImageEnvironmentFactory(
|
||||
InstallerRegistry installerRegistry,
|
||||
RecipeRetriever recipeRetriever,
|
||||
MachineConfigsValidator machinesValidator,
|
||||
@Named("che.workspace.default_memory_mb") long defaultMachineMemorySizeMB) {
|
||||
super(installerRegistry, recipeRetriever, machinesValidator, defaultMachineMemorySizeMB);
|
||||
super(installerRegistry, recipeRetriever, machinesValidator);
|
||||
this.defaultMachineMemorySizeAttribute =
|
||||
String.valueOf(defaultMachineMemorySizeMB * 1024 * 1024);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -72,6 +78,19 @@ public class DockerImageEnvironmentFactory
|
|||
|
||||
checkArgument(dockerImage != null, "Docker image should not be null.");
|
||||
|
||||
addRamLimitAttribute(machines);
|
||||
|
||||
return new DockerImageEnvironment(dockerImage, recipe, machines, warnings);
|
||||
}
|
||||
|
||||
private void addRamLimitAttribute(Map<String, InternalMachineConfig> machines) {
|
||||
// sets default ram limit attribute if not present
|
||||
for (InternalMachineConfig machineConfig : machines.values()) {
|
||||
if (isNullOrEmpty(machineConfig.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE))) {
|
||||
machineConfig
|
||||
.getAttributes()
|
||||
.put(MEMORY_LIMIT_ATTRIBUTE, defaultMachineMemorySizeAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ import org.testng.annotations.Test;
|
|||
@Listeners(MockitoTestNGListener.class)
|
||||
public class ComposeEnvironmentFactoryTest {
|
||||
|
||||
private static final long DEFAULT_RAM_LIMIT_MB = 2048;
|
||||
private static final long BYTES_IN_MB = 1024 * 1024;
|
||||
private static final String MACHINE_NAME_1 = "machine1";
|
||||
private static final String MACHINE_NAME_2 = "machine2";
|
||||
|
||||
|
|
@ -60,13 +62,13 @@ public class ComposeEnvironmentFactoryTest {
|
|||
machinesValidator,
|
||||
composeValidator,
|
||||
startStrategy,
|
||||
2048);
|
||||
DEFAULT_RAM_LIMIT_MB);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetsRamLimitAttributeFromComposeService() throws Exception {
|
||||
final long firstMachineLimit = 3072;
|
||||
final long secondMachineLimit = 1028;
|
||||
final long firstMachineLimit = 3072 * BYTES_IN_MB;
|
||||
final long secondMachineLimit = 1028 * BYTES_IN_MB;
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(
|
||||
MACHINE_NAME_1,
|
||||
|
|
@ -89,7 +91,7 @@ public class ComposeEnvironmentFactoryTest {
|
|||
|
||||
@Test
|
||||
public void testDoNotOverrideRamLimitAttributeWhenItAlreadyPresent() throws Exception {
|
||||
final long customRamLimit = 3072;
|
||||
final long customRamLimit = 3072 * BYTES_IN_MB;
|
||||
final Map<String, String> attributes =
|
||||
ImmutableMap.of(MEMORY_LIMIT_ATTRIBUTE, String.valueOf(customRamLimit));
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
|
|
@ -108,7 +110,7 @@ public class ComposeEnvironmentFactoryTest {
|
|||
@Test
|
||||
public void testAddsMachineConfIntoEnvAndSetsRamLimAttributeWhenMachinePresentOnlyInRecipe()
|
||||
throws Exception {
|
||||
final long customRamLimit = 2048;
|
||||
final long customRamLimit = 3072 * BYTES_IN_MB;
|
||||
final Map<String, InternalMachineConfig> machines = new HashMap<>();
|
||||
final Map<String, ComposeService> services =
|
||||
ImmutableMap.of(MACHINE_NAME_1, mockComposeService(customRamLimit));
|
||||
|
|
@ -121,6 +123,21 @@ public class ComposeEnvironmentFactoryTest {
|
|||
assertTrue(Arrays.equals(actual, expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRamLimitAttributeWhenRamLimitIsMissingInRecipeAndConfig() throws Exception {
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(MACHINE_NAME_1, mockInternalMachineConfig(new HashMap<>()));
|
||||
final Map<String, ComposeService> services =
|
||||
ImmutableMap.of(MACHINE_NAME_1, mockComposeService(0));
|
||||
|
||||
composeEnvironmentFactory.addRamLimitAttribute(machines, services);
|
||||
|
||||
final long[] actual = machinesRam(machines.values());
|
||||
final long[] expected = new long[actual.length];
|
||||
fill(expected, DEFAULT_RAM_LIMIT_MB * BYTES_IN_MB);
|
||||
assertTrue(Arrays.equals(actual, expected));
|
||||
}
|
||||
|
||||
private static InternalMachineConfig mockInternalMachineConfig(Map<String, String> attributes) {
|
||||
final InternalMachineConfig machineConfigMock = mock(InternalMachineConfig.class);
|
||||
when(machineConfigMock.getAttributes()).thenReturn(attributes);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* 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:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.environment.dockerfile;
|
||||
|
||||
import static java.util.Arrays.fill;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.installer.server.InstallerRegistry;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.MachineConfigsValidator;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/** @author Alexander Garagatyi */
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class DockerfileEnvironmentFactoryTest {
|
||||
|
||||
private static final long DEFAULT_RAM_LIMIT_MB = 2048;
|
||||
private static final long BYTES_IN_MB = 1024 * 1024;
|
||||
private static final String MACHINE_NAME = "machine";
|
||||
|
||||
@Mock private InternalRecipe recipe;
|
||||
@Mock private InstallerRegistry installerRegistry;
|
||||
@Mock private RecipeRetriever recipeRetriever;
|
||||
@Mock private MachineConfigsValidator machinesValidator;
|
||||
|
||||
private DockerfileEnvironmentFactory factory;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
factory =
|
||||
new DockerfileEnvironmentFactory(
|
||||
installerRegistry, recipeRetriever, machinesValidator, DEFAULT_RAM_LIMIT_MB);
|
||||
|
||||
when(recipe.getType()).thenReturn(DockerfileEnvironment.TYPE);
|
||||
when(recipe.getContent()).thenReturn("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRamLimitAttributeWhenRamLimitIsMissingInConfig() throws Exception {
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(MACHINE_NAME, mockInternalMachineConfig(new HashMap<>()));
|
||||
|
||||
factory.doCreate(recipe, machines, Collections.emptyList());
|
||||
|
||||
final long[] actual = machinesRam(machines.values());
|
||||
final long[] expected = new long[actual.length];
|
||||
fill(expected, DEFAULT_RAM_LIMIT_MB * BYTES_IN_MB);
|
||||
assertTrue(Arrays.equals(actual, expected));
|
||||
}
|
||||
|
||||
private static InternalMachineConfig mockInternalMachineConfig(Map<String, String> attributes) {
|
||||
final InternalMachineConfig machineConfigMock = mock(InternalMachineConfig.class);
|
||||
when(machineConfigMock.getAttributes()).thenReturn(attributes);
|
||||
return machineConfigMock;
|
||||
}
|
||||
|
||||
private static long[] machinesRam(Collection<InternalMachineConfig> configs) {
|
||||
return configs
|
||||
.stream()
|
||||
.mapToLong(m -> Long.parseLong(m.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE)))
|
||||
.toArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* 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:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage;
|
||||
|
||||
import static java.util.Arrays.fill;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.installer.server.InstallerRegistry;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.MachineConfigsValidator;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/** @author Alexander Garagatyi */
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class DockerImageEnvironmentFactoryTest {
|
||||
private static final long DEFAULT_RAM_LIMIT_MB = 2048;
|
||||
private static final long BYTES_IN_MB = 1024 * 1024;
|
||||
private static final String MACHINE_NAME = "machine";
|
||||
|
||||
@Mock private InternalRecipe recipe;
|
||||
@Mock private InstallerRegistry installerRegistry;
|
||||
@Mock private RecipeRetriever recipeRetriever;
|
||||
@Mock private MachineConfigsValidator machinesValidator;
|
||||
|
||||
private DockerImageEnvironmentFactory factory;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
factory =
|
||||
new DockerImageEnvironmentFactory(
|
||||
installerRegistry, recipeRetriever, machinesValidator, DEFAULT_RAM_LIMIT_MB);
|
||||
|
||||
when(recipe.getType()).thenReturn(DockerImageEnvironment.TYPE);
|
||||
when(recipe.getContent()).thenReturn("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRamLimitAttributeWhenRamLimitIsMissingInConfig() throws Exception {
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(MACHINE_NAME, mockInternalMachineConfig(new HashMap<>()));
|
||||
|
||||
factory.doCreate(recipe, machines, Collections.emptyList());
|
||||
|
||||
final long[] actual = machinesRam(machines.values());
|
||||
final long[] expected = new long[actual.length];
|
||||
fill(expected, DEFAULT_RAM_LIMIT_MB * BYTES_IN_MB);
|
||||
assertTrue(Arrays.equals(actual, expected));
|
||||
}
|
||||
|
||||
private static InternalMachineConfig mockInternalMachineConfig(Map<String, String> attributes) {
|
||||
final InternalMachineConfig machineConfigMock = mock(InternalMachineConfig.class);
|
||||
when(machineConfigMock.getAttributes()).thenReturn(attributes);
|
||||
return machineConfigMock;
|
||||
}
|
||||
|
||||
private static long[] machinesRam(Collection<InternalMachineConfig> configs) {
|
||||
return configs
|
||||
.stream()
|
||||
.mapToLong(m -> Long.parseLong(m.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE)))
|
||||
.toArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
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:
|
||||
Red Hat, Inc. - initial API and implementation
|
||||
|
||||
-->
|
||||
<configuration>
|
||||
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="file" class="ch.qos.logback.core.FileAppender">
|
||||
<File>target/log/log.log</File>
|
||||
<encoder>
|
||||
<pattern>%-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="stdout"/>
|
||||
<appender-ref ref="file"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
|
|
@ -64,6 +64,7 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<Open
|
|||
|
||||
private final OpenShiftClientFactory clientFactory;
|
||||
private final OpenShiftEnvironmentValidator envValidator;
|
||||
private final String defaultMachineMemorySizeAttribute;
|
||||
|
||||
@Inject
|
||||
public OpenShiftEnvironmentFactory(
|
||||
|
|
@ -73,9 +74,11 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<Open
|
|||
OpenShiftClientFactory clientFactory,
|
||||
OpenShiftEnvironmentValidator envValidator,
|
||||
@Named("che.workspace.default_memory_mb") long defaultMachineMemorySizeMB) {
|
||||
super(installerRegistry, recipeRetriever, machinesValidator, defaultMachineMemorySizeMB);
|
||||
super(installerRegistry, recipeRetriever, machinesValidator);
|
||||
this.clientFactory = clientFactory;
|
||||
this.envValidator = envValidator;
|
||||
this.defaultMachineMemorySizeAttribute =
|
||||
String.valueOf(defaultMachineMemorySizeMB * 1024 * 1024);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -172,6 +175,8 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<Open
|
|||
final long ramLimit = Containers.getRamLimit(container);
|
||||
if (ramLimit > 0) {
|
||||
attributes.put(MEMORY_LIMIT_ATTRIBUTE, String.valueOf(ramLimit));
|
||||
} else {
|
||||
attributes.put(MEMORY_LIMIT_ATTRIBUTE, defaultMachineMemorySizeAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ import org.testng.annotations.Test;
|
|||
public class OpenShiftEnvironmentFactoryTest {
|
||||
|
||||
private static final String YAML_RECIPE = "application/x-yaml";
|
||||
private static final long BYTES_IN_MB = 1024 * 1024;
|
||||
private static final long DEFAULT_RAM_LIMIT_MB = 2048;
|
||||
public static final String MACHINE_NAME_1 = "machine1";
|
||||
public static final String MACHINE_NAME_2 = "machine2";
|
||||
|
|
@ -141,8 +142,8 @@ public class OpenShiftEnvironmentFactoryTest {
|
|||
|
||||
@Test
|
||||
public void testSetsRamLimitAttributeFromOpenShiftResource() throws Exception {
|
||||
final long firstMachineRamLimit = 3072;
|
||||
final long secondMachineRamLimit = 1024;
|
||||
final long firstMachineRamLimit = 3072 * BYTES_IN_MB;
|
||||
final long secondMachineRamLimit = 1024 * BYTES_IN_MB;
|
||||
when(machineConfig1.getAttributes()).thenReturn(new HashMap<>());
|
||||
when(machineConfig2.getAttributes()).thenReturn(new HashMap<>());
|
||||
final Set<Pod> pods =
|
||||
|
|
@ -159,13 +160,13 @@ public class OpenShiftEnvironmentFactoryTest {
|
|||
|
||||
@Test
|
||||
public void testDoNotOverrideRamLimitAttributeWhenItAlreadyPresent() throws Exception {
|
||||
final long customRamLimit = 3072;
|
||||
final long customRamLimit = 3072 * BYTES_IN_MB;
|
||||
final Map<String, String> attributes =
|
||||
ImmutableMap.of(MEMORY_LIMIT_ATTRIBUTE, String.valueOf(customRamLimit));
|
||||
when(machineConfig1.getAttributes()).thenReturn(attributes);
|
||||
when(machineConfig2.getAttributes()).thenReturn(attributes);
|
||||
final Pod pod1 = mockPod(MACHINE_NAME_1, 0);
|
||||
final Pod pod2 = mockPod(MACHINE_NAME_2, 0);
|
||||
final Pod pod1 = mockPod(MACHINE_NAME_1, 0L);
|
||||
final Pod pod2 = mockPod(MACHINE_NAME_2, 0L);
|
||||
final Set<Pod> pods = ImmutableSet.of(pod1, pod2);
|
||||
|
||||
osEnvironmentFactory.addRamLimitAttribute(machines, pods);
|
||||
|
|
@ -179,7 +180,7 @@ public class OpenShiftEnvironmentFactoryTest {
|
|||
@Test
|
||||
public void testAddsMachineConfIntoEnvAndSetsRamLimAttributeWhenMachinePresentOnlyInRecipe()
|
||||
throws Exception {
|
||||
final long customRamLimit = 2048;
|
||||
final long customRamLimit = 2048 * BYTES_IN_MB;
|
||||
final Map<String, InternalMachineConfig> machines = new HashMap<>();
|
||||
final Set<Pod> pods = ImmutableSet.of(mockPod(MACHINE_NAME_2, customRamLimit));
|
||||
|
||||
|
|
@ -191,20 +192,40 @@ public class OpenShiftEnvironmentFactoryTest {
|
|||
assertTrue(Arrays.equals(actual, expected));
|
||||
}
|
||||
|
||||
private static Pod mockPod(String machineName, long ramLimit) {
|
||||
@Test
|
||||
public void testSetsDefaultRamLimitAttributeIfRamLimitIsMissingInRecipeAndConfig()
|
||||
throws Exception {
|
||||
final long firstMachineRamLimit = 3072 * BYTES_IN_MB;
|
||||
when(machineConfig1.getAttributes()).thenReturn(new HashMap<>());
|
||||
when(machineConfig2.getAttributes()).thenReturn(new HashMap<>());
|
||||
final Set<Pod> pods =
|
||||
ImmutableSet.of(
|
||||
mockPod(MACHINE_NAME_1, firstMachineRamLimit), mockPod(MACHINE_NAME_2, null));
|
||||
|
||||
osEnvironmentFactory.addRamLimitAttribute(machines, pods);
|
||||
|
||||
final long[] actual = machinesRam(machines.values());
|
||||
final long[] expected = new long[] {firstMachineRamLimit, DEFAULT_RAM_LIMIT_MB * BYTES_IN_MB};
|
||||
assertTrue(Arrays.equals(actual, expected));
|
||||
}
|
||||
|
||||
/** If provided {@code ramLimit} is {@code null} ram limit won't be set in POD */
|
||||
private static Pod mockPod(String machineName, Long ramLimit) {
|
||||
final String containerName = "container_" + machineName;
|
||||
final Container containerMock = mock(Container.class);
|
||||
final ResourceRequirements resourcesMock = mock(ResourceRequirements.class);
|
||||
final Quantity quantityMock = mock(Quantity.class);
|
||||
final Pod podMock = mock(Pod.class);
|
||||
final PodSpec specMock = mock(PodSpec.class);
|
||||
final ObjectMeta metadataMock = mock(ObjectMeta.class);
|
||||
when(podMock.getSpec()).thenReturn(specMock);
|
||||
when(podMock.getMetadata()).thenReturn(metadataMock);
|
||||
when(quantityMock.getAmount()).thenReturn(String.valueOf(ramLimit));
|
||||
when(resourcesMock.getLimits()).thenReturn(ImmutableMap.of("memory", quantityMock));
|
||||
if (ramLimit != null) {
|
||||
final Quantity quantityMock = mock(Quantity.class);
|
||||
final ResourceRequirements resourcesMock = mock(ResourceRequirements.class);
|
||||
when(quantityMock.getAmount()).thenReturn(String.valueOf(ramLimit));
|
||||
when(resourcesMock.getLimits()).thenReturn(ImmutableMap.of("memory", quantityMock));
|
||||
when(containerMock.getResources()).thenReturn(resourcesMock);
|
||||
}
|
||||
when(containerMock.getName()).thenReturn(containerName);
|
||||
when(containerMock.getResources()).thenReturn(resourcesMock);
|
||||
when(metadataMock.getAnnotations())
|
||||
.thenReturn(
|
||||
ImmutableMap.of(format(MACHINE_NAME_ANNOTATION_FMT, containerName), machineName));
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import org.eclipse.che.api.core.ServerException;
|
|||
import org.eclipse.che.api.core.ValidationException;
|
||||
import org.eclipse.che.api.core.model.workspace.Runtime;
|
||||
import org.eclipse.che.api.core.model.workspace.config.Environment;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
|
||||
|
|
@ -50,7 +51,8 @@ public class EnvironmentRamCalculator {
|
|||
.getMachines()
|
||||
.values()
|
||||
.stream()
|
||||
.mapToLong(m -> Long.parseLong(m.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE)))
|
||||
.mapToLong(
|
||||
m -> parseMemoryAttributeValue(m.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE)))
|
||||
.sum()
|
||||
/ BYTES_TO_MEGABYTES_DIVIDER;
|
||||
} catch (InfrastructureException | ValidationException | NotFoundException ex) {
|
||||
|
|
@ -68,11 +70,31 @@ public class EnvironmentRamCalculator {
|
|||
.getMachines()
|
||||
.values()
|
||||
.stream()
|
||||
.mapToLong(m -> Long.parseLong(m.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE)))
|
||||
.mapToLong(
|
||||
m -> parseMemoryAttributeValue(m.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE)))
|
||||
.sum()
|
||||
/ BYTES_TO_MEGABYTES_DIVIDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse {@link MachineConfig#MEMORY_LIMIT_ATTRIBUTE} value to {@code Long}.
|
||||
*
|
||||
* @param attributeValue value of {@link MachineConfig#MEMORY_LIMIT_ATTRIBUTE} attribute from
|
||||
* machine config or runtime
|
||||
* @return long value parsed from provided string attribute value or {@code 0} if {@code null} is
|
||||
* provided
|
||||
* @throws NumberFormatException if provided value is neither {@code null} nor valid stringified
|
||||
* long
|
||||
* @see Long#parseLong(String)
|
||||
*/
|
||||
private long parseMemoryAttributeValue(String attributeValue) {
|
||||
if (attributeValue == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return Long.parseLong(attributeValue);
|
||||
}
|
||||
}
|
||||
|
||||
private InternalEnvironment getInternalEnvironment(Environment environment)
|
||||
throws InfrastructureException, ValidationException, NotFoundException {
|
||||
final String recipeType = environment.getRecipe().getType();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import static org.mockito.Mockito.when;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Collections;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.model.workspace.Runtime;
|
||||
import org.eclipse.che.api.core.model.workspace.config.Environment;
|
||||
|
|
@ -84,6 +85,18 @@ public class EnvironmentRamCalculatorTest {
|
|||
assertEquals(ram, 2560);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculatesRamOfEnvironmentWhenSomeMachineConfigHasNoAttribute() throws Exception {
|
||||
when(machineConfig1.getAttributes()).thenReturn(Collections.emptyMap());
|
||||
when(machineConfig2.getAttributes())
|
||||
.thenReturn(ImmutableMap.of(MEMORY_LIMIT_ATTRIBUTE, "536870912"));
|
||||
when(recipeMock.getType()).thenReturn(RECIPE_TYPE);
|
||||
|
||||
final long ram = envRamCalculator.calculate(environment);
|
||||
|
||||
assertEquals(ram, 512);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ServerException.class)
|
||||
public void testThrowServerExceptionWhenNoEnvFactoryForGivenRecipeTypeFound() throws Exception {
|
||||
when(recipeMock.getType()).thenReturn("unsupported");
|
||||
|
|
@ -100,4 +113,14 @@ public class EnvironmentRamCalculatorTest {
|
|||
|
||||
assertEquals(ram, 1536);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculatesRamOfRuntimeWhenSomeMachineHasNoAttribute() throws Exception {
|
||||
when(machine1.getAttributes()).thenReturn(ImmutableMap.of(MEMORY_LIMIT_ATTRIBUTE, "805306368"));
|
||||
when(machine2.getAttributes()).thenReturn(Collections.emptyMap());
|
||||
|
||||
final long ram = envRamCalculator.calculate(runtime);
|
||||
|
||||
assertEquals(ram, 768);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@
|
|||
*/
|
||||
package org.eclipse.che.api.workspace.server.spi.environment;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -50,18 +47,14 @@ public abstract class InternalEnvironmentFactory<T extends InternalEnvironment>
|
|||
private final InstallerRegistry installerRegistry;
|
||||
private final RecipeRetriever recipeRetriever;
|
||||
private final MachineConfigsValidator machinesValidator;
|
||||
private final String defaultMachineMemorySizeAttribute;
|
||||
|
||||
public InternalEnvironmentFactory(
|
||||
InstallerRegistry installerRegistry,
|
||||
RecipeRetriever recipeRetriever,
|
||||
MachineConfigsValidator machinesValidator,
|
||||
long defaultMachineMemorySizeMB) {
|
||||
MachineConfigsValidator machinesValidator) {
|
||||
this.installerRegistry = installerRegistry;
|
||||
this.recipeRetriever = recipeRetriever;
|
||||
this.machinesValidator = machinesValidator;
|
||||
this.defaultMachineMemorySizeAttribute =
|
||||
String.valueOf(defaultMachineMemorySizeMB * 1024 * 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,23 +106,16 @@ public abstract class InternalEnvironmentFactory<T extends InternalEnvironment>
|
|||
|
||||
machinesValidator.validate(machines);
|
||||
|
||||
final T environment = doCreate(recipe, machines, warnings);
|
||||
|
||||
// sets default ram limit attribute if not present
|
||||
for (InternalMachineConfig machineConfig : environment.getMachines().values()) {
|
||||
if (isNullOrEmpty(machineConfig.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE))) {
|
||||
machineConfig
|
||||
.getAttributes()
|
||||
.put(MEMORY_LIMIT_ATTRIBUTE, defaultMachineMemorySizeAttribute);
|
||||
}
|
||||
}
|
||||
return environment;
|
||||
return doCreate(recipe, machines, warnings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation validates downloaded recipe and creates specific InternalEnvironment. Returned
|
||||
* InternalEnvironment must contains all machine that are defined in recipe and in source machine
|
||||
* collection.
|
||||
* Implementation validates downloaded recipe and creates specific InternalEnvironment.
|
||||
*
|
||||
* <p>Returned InternalEnvironment must contains all machine that are defined in recipe and in
|
||||
* source machines collection. Also, if memory limitation is supported, it may add memory limit
|
||||
* attribute {@link MachineConfig#MEMORY_LIMIT_ATTRIBUTE} from recipe or configured system-wide
|
||||
* default value.
|
||||
*
|
||||
* @param recipe downloaded recipe
|
||||
* @param machines machines configuration
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import static org.mockito.Mockito.spy;
|
|||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
|
@ -176,21 +175,6 @@ public class InternalEnvironmentFactoryTest {
|
|||
ImmutableMap.of("serverWithoutProtocol", normalizedServer, "udpServer", udpServer));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetsDefaultRamLimitAttributeToMachineThatDoesNotContainIt() throws Exception {
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
final InternalEnvironment internalEnv = mock(InternalEnvironment.class);
|
||||
final InternalMachineConfig machine = mock(InternalMachineConfig.class);
|
||||
when(environmentFactory.doCreate(any(), any(), any())).thenReturn(internalEnv);
|
||||
when(internalEnv.getMachines()).thenReturn(ImmutableMap.of("testMachine", machine));
|
||||
when(machine.getAttributes()).thenReturn(attributes);
|
||||
|
||||
environmentFactory.create(mock(Environment.class));
|
||||
|
||||
assertTrue(attributes.containsKey(MEMORY_LIMIT_ATTRIBUTE));
|
||||
assertEquals(attributes.get(MEMORY_LIMIT_ATTRIBUTE), String.valueOf(RAM_LIMIT * 2 << 19));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoNotOverrideRamLimitAttributeWhenMachineAlreadyContainsIt() throws Exception {
|
||||
final String ramLimit = "2147483648";
|
||||
|
|
@ -216,7 +200,7 @@ public class InternalEnvironmentFactoryTest {
|
|||
InstallerRegistry installerRegistry,
|
||||
RecipeRetriever recipeRetriever,
|
||||
MachineConfigsValidator machinesValidator) {
|
||||
super(installerRegistry, recipeRetriever, machinesValidator, RAM_LIMIT);
|
||||
super(installerRegistry, recipeRetriever, machinesValidator);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue