Skip to content

Commit 143ea9c

Browse files
committed
Fix #34844: allow "m" suffix in cpu limit of Docker
1 parent d407af9 commit 143ea9c

5 files changed

Lines changed: 37 additions & 8 deletions

File tree

src/main/java/eu/openanalytics/containerproxy/backend/docker/AbstractDockerBackend.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,14 @@ protected String toJson(Object object) {
167167
}
168168
}
169169

170+
protected long getCpuQuota(Long cpuPeriod, String cpu) {
171+
double converted;
172+
if (cpu.endsWith("m")) {
173+
converted = Double.parseDouble(cpu.substring(0, cpu.length() - 1)) / 1_000;
174+
} else {
175+
converted = Double.parseDouble(cpu);
176+
}
177+
return Double.valueOf(cpuPeriod.doubleValue() * converted).longValue();
178+
}
179+
170180
}

src/main/java/eu/openanalytics/containerproxy/backend/docker/DockerEngineBackend.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,15 @@ public Proxy startContainer(Authentication user, Container initialContainer, Con
122122
}
123123
}
124124
hostConfigBuilder.portBindings(dockerPortBindings);
125-
126125
hostConfigBuilder.memoryReservation(memoryToBytes(spec.getMemoryRequest().getValueOrNull()));
127126
hostConfigBuilder.memory(memoryToBytes(spec.getMemoryLimit().getValueOrNull()));
127+
if (spec.getCpuRequest().isPresent()) {
128+
slog.warn(proxy, "Ignoring 'container-memory-request', this is not supported in Docker.");
129+
}
128130
if (spec.getCpuLimit().isPresent()) {
129131
// Workaround, see https://github.com/spotify/docker-client/issues/959
130-
long period = 100000;
131-
long quota = (long) (period * Float.parseFloat(spec.getCpuLimit().getValue()));
132+
long period = 100_000;
133+
long quota = getCpuQuota(period, spec.getCpuLimit().getValue());
132134
hostConfigBuilder.cpuPeriod(period);
133135
hostConfigBuilder.cpuQuota(quota);
134136
}

src/main/java/eu/openanalytics/containerproxy/backend/docker/DockerSwarmBackend.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public Proxy startContainer(Authentication user, Container initialContainer, Con
149149
// reservations are used by the Docker swarm scheduler
150150
if (spec.getCpuRequest().isPresent()) {
151151
// note: 1 CPU = 1 * 10e8 nanoCpu -> equivalent to --cpus option
152-
reservationsBuilder.nanoCpus((long) (Double.parseDouble(spec.getCpuRequest().getValue()) * 10e8));
152+
reservationsBuilder.nanoCpus(getCpuQuota(1000_000_000L, spec.getCpuRequest().getValue()));
153153
}
154154
if (spec.getMemoryRequest().isPresent()) {
155155
reservationsBuilder.memoryBytes(memoryToBytes(spec.getMemoryRequest().getValue()));
@@ -158,7 +158,7 @@ public Proxy startContainer(Authentication user, Container initialContainer, Con
158158
Resources.Builder limitsBuilder = Resources.builder();
159159
if (spec.getCpuLimit().isPresent()) {
160160
// note: 1 CPU = 1 * 10e8 nanoCpu -> equivalent to --cpus option
161-
limitsBuilder.nanoCpus((long) (Double.parseDouble(spec.getCpuLimit().getValue()) * 10e8));
161+
limitsBuilder.nanoCpus(getCpuQuota(1000_000_000L, spec.getCpuLimit().getValue()));
162162
}
163163
if (spec.getMemoryLimit().isPresent()) {
164164
limitsBuilder.memoryBytes(memoryToBytes(spec.getMemoryLimit().getValue()));

src/test/java/eu/openanalytics/containerproxy/test/proxy/TestIntegrationOnDocker.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import org.junit.jupiter.api.AfterAll;
3131
import org.junit.jupiter.api.Assertions;
3232
import org.junit.jupiter.api.Test;
33+
import org.junit.jupiter.params.ParameterizedTest;
34+
import org.junit.jupiter.params.provider.MethodSource;
35+
import org.junit.jupiter.params.provider.ValueSource;
3336
import org.mandas.docker.client.DefaultDockerClient;
3437
import org.mandas.docker.client.DockerClient;
3538
import org.mandas.docker.client.builder.jersey.JerseyDockerClientBuilder;
@@ -55,11 +58,12 @@ public static void afterAll() {
5558
inst.close();
5659
}
5760

58-
@Test
59-
public void testMemorySpecification() throws DockerCertificateException, DockerException, InterruptedException, InvalidParametersException {
61+
@ValueSource(strings = {"01_hello_memory1", "01_hello_memory5"})
62+
@ParameterizedTest
63+
public void testMemoryAndCpuSpecification(String value) throws DockerCertificateException, DockerException, InterruptedException, InvalidParametersException {
6064
try (ContainerSetup containerSetup = new ContainerSetup("docker")) {
6165
try (DefaultDockerClient dockerClient = new JerseyDockerClientBuilder().fromEnv().build()) {
62-
String id = inst.client.startProxy("01_hello_memory1");
66+
String id = inst.client.startProxy(value);
6367
Proxy proxy = inst.proxyService.getProxy(id);
6468

6569
List<Container> containers = dockerClient.listContainers(DockerClient.ListContainersParam.withStatusRunning(), DockerClient.ListContainersParam.withLabel("openanalytics.eu/sp-proxied-app"));
@@ -69,6 +73,8 @@ public void testMemorySpecification() throws DockerCertificateException, DockerE
6973
ContainerInfo containerInfo = dockerClient.inspectContainer(container.id());
7074
Assertions.assertEquals(268435456, containerInfo.hostConfig().memoryReservation());
7175
Assertions.assertEquals(1073741824, containerInfo.hostConfig().memory());
76+
Assertions.assertEquals(100_000, containerInfo.hostConfig().cpuPeriod());
77+
Assertions.assertEquals(25_000, containerInfo.hostConfig().cpuQuota());
7278

7379
inst.proxyService.stopProxy(null, proxy, true).run();
7480
}

src/test/resources/application-test-docker.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ proxy:
4646
port: 3838
4747
memory-request: 256Mi
4848
memory-limit: 1G
49+
cpu-limit: 250m
4950
- id: 01_hello_memory2
5051
container-specs:
5152
- image: "openanalytics/shinyproxy-integration-test-app"
@@ -70,3 +71,13 @@ proxy:
7071
- name: default
7172
port: 3838
7273
memory-request: 0,5Gi
74+
- id: 01_hello_memory5
75+
container-specs:
76+
- image: "openanalytics/shinyproxy-integration-test-app"
77+
cmd: [ "R", "-e", "shinyproxy::run_01_hello()" ]
78+
port-mapping:
79+
- name: default
80+
port: 3838
81+
memory-request: 256Mi
82+
memory-limit: 1G
83+
cpu-limit: 0.25

0 commit comments

Comments
 (0)