fix(runner): support floating-point CPU values in Docker runner (#10366)

This commit is contained in:
Malay Dewangan
2025-07-28 14:21:23 +05:30
committed by GitHub
parent cf3e49a284
commit 25f5ccc6b5
3 changed files with 32 additions and 2 deletions

View File

@@ -14,5 +14,5 @@ public class Cpu {
title = "The maximum amount of CPU resources a container can use.",
description = "Make sure to set that to a numeric value e.g. `cpus: \"1.5\"` or `cpus: \"4\"` or For instance, if the host machine has two CPUs and you set `cpus: \"1.5\"`, the container is guaranteed **at most** one and a half of the CPUs."
)
private Property<Long> cpus;
private Property<Double> cpus;
}

View File

@@ -765,7 +765,8 @@ public class Docker extends TaskRunner<Docker.DockerTaskRunnerDetailResult> {
}
if (this.getCpu() != null && this.getCpu().getCpus() != null) {
hostConfig.withCpuQuota(runContext.render(this.getCpu().getCpus()).as(Long.class).orElseThrow() * 10000L);
Double cpuValue = runContext.render(this.getCpu().getCpus()).as(Double.class).orElseThrow();
hostConfig.withNanoCPUs((long)(cpuValue * 1_000_000_000L));
}
if (this.getMemory() != null) {

View File

@@ -2,15 +2,18 @@ package io.kestra.plugin.scripts.runner.docker;
import io.kestra.core.models.property.Property;
import io.kestra.core.models.tasks.runners.AbstractTaskRunnerTest;
import io.kestra.core.models.tasks.runners.TaskCommands;
import io.kestra.core.models.tasks.runners.TaskRunner;
import io.kestra.plugin.scripts.exec.scripts.runners.CommandsWrapper;
import org.assertj.core.api.Assertions;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.hamcrest.Matchers.containsString;
class DockerTest extends AbstractTaskRunnerTest {
@Override
@@ -37,4 +40,30 @@ class DockerTest extends AbstractTaskRunnerTest {
assertThat(result.getExitCode()).isZero();
Assertions.assertThat(result.getLogConsumer().getStdOutCount()).isEqualTo(1);
}
@Test
void shouldSetCorrectCPULimitsInContainer() throws Exception {
var runContext = runContext(this.runContextFactory);
var cpuConfig = Cpu.builder()
.cpus(Property.ofValue(1.5))
.build();
var docker = Docker.builder()
.image("rockylinux:9.3-minimal")
.cpu(cpuConfig)
.build();
var taskCommands = new CommandsWrapper(runContext).withCommands(Property.ofValue(List.of(
"/bin/sh", "-c",
"CPU_LIMIT=$(cat /sys/fs/cgroup/cpu.max || cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us) && " +
"echo \"::{\\\"outputs\\\":{\\\"cpuLimit\\\":\\\"$CPU_LIMIT\\\"}}::\""
)));
var result = docker.run(runContext, taskCommands, Collections.emptyList());
assertThat(result).isNotNull();
assertThat(result.getExitCode()).isZero();
MatcherAssert.assertThat((String) result.getLogConsumer().getOutputs().get("cpuLimit"), containsString("150000"));
assertThat(result.getLogConsumer().getStdOutCount()).isEqualTo(1);
}
}