diff --git a/docs/attachments/docker-plugin-configuration-script.groovy b/docs/attachments/docker-plugin-configuration-script.groovy index 2c6f2057e..e5d026f42 100644 --- a/docs/attachments/docker-plugin-configuration-script.groovy +++ b/docs/attachments/docker-plugin-configuration-script.groovy @@ -32,6 +32,7 @@ def templateBaseParameters = [ // bindPorts: '', // capabilitiesToAddString: '', // capabilitiesToDropString: '', + // cgroupParent: '', // cpus: '', // cpuPeriod: (Long)null, // cpuQuota: (Long)null, diff --git a/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplate.java b/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplate.java index 1593f9fd3..6ba70bd98 100644 --- a/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplate.java +++ b/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplate.java @@ -200,6 +200,10 @@ public Integer getMemorySwap() { return dockerTemplateBase.getMemorySwap(); } + public String getCgroupParent() { + return dockerTemplateBase.getCgroupParent(); + } + public String getCpus() { return dockerTemplateBase.getCpus(); } diff --git a/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplateBase.java b/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplateBase.java index d5ef2bb16..0882628d3 100644 --- a/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplateBase.java +++ b/src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplateBase.java @@ -124,6 +124,7 @@ public class DockerTemplateBase implements Describable, Seri public @CheckForNull Integer memoryLimit; public @CheckForNull Integer memorySwap; + public @CheckForNull String cgroupParent; public @CheckForNull String cpus; public @CheckForNull Long cpuPeriod; public @CheckForNull Long cpuQuota; @@ -460,6 +461,16 @@ public void setMemorySwap(Integer memorySwap) { this.memorySwap = memorySwap; } + @CheckForNull + public String getCgroupParent() { + return Util.fixEmpty(cgroupParent); + } + + @DataBoundSetter + public void setCgroupParent(String cgroupParent) { + this.cgroupParent = Util.fixEmpty(cgroupParent); + } + @CheckForNull public String getCpus() { return Util.fixEmpty(cpus); @@ -817,6 +828,11 @@ public CreateContainerCmd fillContainerConfig(CreateContainerCmd containerConfig } } + final String cgroupParentOrNull = getCgroupParent(); + if (cgroupParentOrNull != null && !Strings.isNullOrEmpty(cgroupParentOrNull)) { + hostConfig(containerConfig).withCgroupParent(cgroupParentOrNull); + } + final String[] dnsHostsOrNull = getDnsHosts(); if (dnsHostsOrNull != null && dnsHostsOrNull.length > 0) { hostConfig(containerConfig).withDns(dnsHostsOrNull); @@ -1149,6 +1165,9 @@ public boolean equals(Object o) { if (!Objects.equals(memorySwap, that.memorySwap)) { return false; } + if (!Objects.equals(cgroupParent, that.cgroupParent)) { + return false; + } if (!Objects.equals(cpus, that.cpus)) { return false; } @@ -1206,6 +1225,7 @@ public int hashCode() { result = 31 * result + (bindAllPorts ? 1 : 0); result = 31 * result + (memoryLimit != null ? memoryLimit.hashCode() : 0); result = 31 * result + (memorySwap != null ? memorySwap.hashCode() : 0); + result = 31 * result + (cgroupParent != null ? cgroupParent.hashCode() : 0); result = 31 * result + (cpus != null ? cpus.hashCode() : 0); result = 31 * result + (cpuPeriod != null ? cpuPeriod.hashCode() : 0); result = 31 * result + (cpuQuota != null ? cpuQuota.hashCode() : 0); @@ -1244,6 +1264,7 @@ public String toString() { bldToString(sb, "bindAllPorts", bindAllPorts); bldToString(sb, "memoryLimit", memoryLimit); bldToString(sb, "memorySwap", memorySwap); + bldToString(sb, "cgroupParent", cgroupParent); bldToString(sb, "cpus", cpus); bldToString(sb, "cpuPeriod", cpuPeriod); bldToString(sb, "cpuQuota", cpuQuota); diff --git a/src/main/java/com/nirima/jenkins/plugins/docker/builder/DockerBuilderControlOptionRun.java b/src/main/java/com/nirima/jenkins/plugins/docker/builder/DockerBuilderControlOptionRun.java index 6dc6643e3..8bffff412 100644 --- a/src/main/java/com/nirima/jenkins/plugins/docker/builder/DockerBuilderControlOptionRun.java +++ b/src/main/java/com/nirima/jenkins/plugins/docker/builder/DockerBuilderControlOptionRun.java @@ -51,6 +51,7 @@ public class DockerBuilderControlOptionRun extends DockerBuilderControlCloudOpti public final String bindPorts; public final Integer memoryLimit; public final Integer memorySwap; + public final String cgroupParent; public final String cpus; public final Long cpuPeriod; public final Long cpuQuota; @@ -75,6 +76,7 @@ public DockerBuilderControlOptionRun( String extraGroupsString, Integer memoryLimit, Integer memorySwap, + String cgroupParent, String cpus, Long cpuPeriod, Long cpuQuota, @@ -102,6 +104,7 @@ public DockerBuilderControlOptionRun( this.bindPorts = bindPorts; this.memoryLimit = memoryLimit; this.memorySwap = memorySwap; + this.cgroupParent = cgroupParent; this.cpus = cpus; this.cpuPeriod = cpuPeriod; this.cpuQuota = cpuQuota; @@ -205,6 +208,7 @@ private void executeOnDocker( tty, macAddress, null); + template.setCgroupParent(cgroupParent); LOG.info("Starting container for image {}", xImage); llog.println("Starting container for image " + xImage); diff --git a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/config.jelly b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/config.jelly index 75cadb152..e8ccbd2a4 100644 --- a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/config.jelly +++ b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/config.jelly @@ -70,6 +70,10 @@ + + + + @@ -127,4 +131,4 @@ - \ No newline at end of file + diff --git a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/help-cgroupParent.html b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/help-cgroupParent.html new file mode 100644 index 000000000..4bb5e9d77 --- /dev/null +++ b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplateBase/help-cgroupParent.html @@ -0,0 +1,4 @@ +
+

This allows agents to run in a cgroup other than the daemon/system default.

+

Please check https://docs.docker.com/reference/cli/docker/container/run/#cgroup-parent for further information.

+
diff --git a/src/test/java/com/nirima/jenkins/plugins/docker/DockerCloudTest.java b/src/test/java/com/nirima/jenkins/plugins/docker/DockerCloudTest.java index bee603e18..e4d3ac250 100644 --- a/src/test/java/com/nirima/jenkins/plugins/docker/DockerCloudTest.java +++ b/src/test/java/com/nirima/jenkins/plugins/docker/DockerCloudTest.java @@ -112,6 +112,7 @@ public void globalConfigRoundtrip() throws Exception { templateBase.setCapabilitiesToAddString("SYS_ADMIN"); templateBase.setCapabilitiesToDropString("CHOWN"); templateBase.setSecurityOptsString("seccomp=unconfined"); + templateBase.setCgroupParent(""); final DockerTemplate template = new DockerTemplate( templateBase, new DockerComputerAttachConnector("jenkins"), "labelString", "remoteFs", "10"); template.setPullStrategy(DockerImagePullStrategy.PULL_NEVER); diff --git a/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateBaseTest.java b/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateBaseTest.java index 4b9ea349b..ddbcc69f0 100644 --- a/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateBaseTest.java +++ b/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateBaseTest.java @@ -252,6 +252,36 @@ private static void testFillContainerCapabilitiesToDrop( } } + @Test + public void fillContainerConfigCgroupParent() { + testFillContainerConfigCgroupParent("not existing", "dummy_cgroup_parent", true); + } + + @Test + public void fillContainerConfigNoCgroupParent() { + testFillContainerConfigCgroupParent("not existing", "", false); + } + + private static void testFillContainerConfigCgroupParent( + final String imageName, final String cgroupParent, final boolean wasSet) { + // Given + final CreateContainerCmd mockCmd = mock(CreateContainerCmd.class); + final HostConfig mockHostConfig = mock(HostConfig.class); + when(mockCmd.getHostConfig()).thenReturn(mockHostConfig); + final DockerTemplateBase instanceUnderTest = new DockerTemplateBase(imageName); + instanceUnderTest.setCgroupParent(cgroupParent); + + // When + instanceUnderTest.fillContainerConfig(mockCmd); + + // Then + if (wasSet) { + verify(mockHostConfig, times(1)).withCgroupParent(cgroupParent); + } else { + verify(mockHostConfig, never()).withCgroupParent(cgroupParent); + } + } + @Test public void fillContainerConfigCpus() { testFillContainerConfigCpus("not existing", "1.5", 1500000000L); diff --git a/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateTest.java b/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateTest.java index 64adbf093..a346c1b7c 100644 --- a/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateTest.java +++ b/src/test/java/com/nirima/jenkins/plugins/docker/DockerTemplateTest.java @@ -18,6 +18,7 @@ public class DockerTemplateTest { String javaPath = " javaPath"; Integer memoryLimit = 1024; Integer memorySwap = 1280; + String cgroupParent = "cgroupParent"; Long cpuPeriod = 0L; Long cpuQuota = 0L; Integer cpuShares = 1000; @@ -72,6 +73,7 @@ private DockerTemplate getDockerTemplateInstanceWithDNSHost(String dnsString) { dockerTemplateBase.setCapabilitiesToAddString(capabilitiesToAddString); dockerTemplateBase.setCapabilitiesToDropString(capabilitiesToDropString); dockerTemplateBase.setSecurityOptsString(securityOptsString); + dockerTemplateBase.setCgroupParent(cgroupParent); return new DockerTemplate(dockerTemplateBase, null, labelString, remoteFs, instanceCapStr); }