Skip to content

Commit

Permalink
Support Compose memory limit byte units (#8837)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkuznyetsov committed Feb 20, 2018
1 parent 49908c5 commit 1904eac
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 0 deletions.
4 changes: 4 additions & 0 deletions infrastructures/docker/environment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-workspace-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.compose.deserializer;

import static java.lang.String.format;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import org.eclipse.che.commons.lang.Size;

/**
* Deserialize Compose memory limit value, which could be either a plain byte number, or a string
* followed by byte units (e.g. "1mb"), which is parsed, using {@link Size} class.
*
* @author Mykhailo Kuznietsov
*/
public class MemLimitDeserializer extends JsonDeserializer<Long> {
private static final String UNSUPPORTED_VALUE_MESSAGE = "Unsupported value '%s'.";

@Override
public Long deserialize(JsonParser jsonParser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
Object memLimit = jsonParser.readValueAs(Object.class);
if (memLimit instanceof Long) {
return (Long) memLimit;
}
if (memLimit instanceof Integer) {
return ((Integer) memLimit).longValue();
}
if (memLimit instanceof String) {
return Size.parseSize((String) memLimit);
}
throw ctxt.mappingException(format(UNSUPPORTED_VALUE_MESSAGE, memLimit));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.stream.Collectors;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.deserializer.CommandDeserializer;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.deserializer.EnvironmentDeserializer;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.deserializer.MemLimitDeserializer;

/**
* Description of docker compose service.
Expand Down Expand Up @@ -55,6 +56,7 @@ public class ComposeService {
@JsonProperty("volumes_from")
private List<String> volumesFrom;

@JsonDeserialize(using = MemLimitDeserializer.class)
@JsonProperty("mem_limit")
private Long memLimit;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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.compose;

import static org.testng.Assert.assertEquals;

import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.spi.environment.MachineConfigsValidator;
import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.deserializer.MemLimitDeserializer;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.model.ComposeRecipe;
import org.mockito.Mock;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

/**
* Test of {@link MemLimitDeserializer} functionality.
*
* @author Mykhailo Kuznietsov
*/
public class MemLimitDeserializerTest {
@Mock private InstallerRegistry installerRegistry;
@Mock private RecipeRetriever recipeRetriever;
@Mock private MachineConfigsValidator machinesValidator;
@Mock private ComposeEnvironmentValidator composeValidator;
@Mock private ComposeServicesStartStrategy startStrategy;

private ComposeEnvironmentFactory factory;

private static final long K = 1024;
private static final long M = 1024 * K;
private static final long G = 1024 * M;

private static final String RECIPE_WITHOUT_MEMORY_LIMIT =
"services:\n" + " machine1:\n" + " mem_limit: %s";

@BeforeMethod
public void setup() {
factory =
new ComposeEnvironmentFactory(
installerRegistry,
recipeRetriever,
machinesValidator,
composeValidator,
startStrategy,
2048);
}

@Test(dataProvider = "validValues")
public void shouldDeserializeValues(Object memoryLimit, Object parsedLimit)
throws ValidationException {
ComposeRecipe recipe = factory.doParse(String.format(RECIPE_WITHOUT_MEMORY_LIMIT, memoryLimit));
assertEquals(recipe.getServices().get("machine1").getMemLimit(), parsedLimit);
}

@Test(dataProvider = "invalidValues", expectedExceptions = ValidationException.class)
public void shouldThrowExceptionOnDeseralization(Object memoryLimit) throws ValidationException {
factory.doParse(String.format(RECIPE_WITHOUT_MEMORY_LIMIT, memoryLimit));
}

@DataProvider(name = "validValues")
public Object[][] validValues() {
return new Object[][] {
{"2048", 2048L},
{"1gb", 1 * G},
{"2g", 2 * G},
{"1073741824", 1 * G},
{"8m", 8 * M},
{"200mb", 200 * M},
{"5k", 5 * K},
{"10kb", 10 * K},
};
}

@DataProvider(name = "invalidValues")
public Object[][] invalidValues() {
return new Object[][] {{"1m1"}, {"notanumber"}, {1024.5}};
}
}

0 comments on commit 1904eac

Please sign in to comment.