From a55ba1f7327cf1de851a6143a9d377f67fa5b67a Mon Sep 17 00:00:00 2001 From: Fabian Wunsch Date: Fri, 5 Aug 2022 14:43:56 +0200 Subject: [PATCH 1/3] Honor template name when limiting agents by template (#816) --- .../jenkins/plugins/docker/DockerCloud.java | 34 ++++++++++++++----- .../docker/DockerTemplate/help-name.html | 4 +++ .../DockerComputerConnectorTest.java | 2 +- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java b/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java index 73f2d4a85..e88ca4d01 100644 --- a/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java +++ b/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java @@ -16,6 +16,7 @@ import com.github.dockerjava.api.command.PushImageCmd; import com.github.dockerjava.api.command.StartContainerCmd; import com.github.dockerjava.api.model.AuthConfig; +import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.Version; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; @@ -601,21 +602,33 @@ public synchronized void removeTemplate(DockerTemplate t) { templates.remove(t); } } + + /** + * @deprecated use countContainersInDocker(String, String) instead + * @see DockerCloud#countContainersInDocker(String, String) + */ + @Deprecated + public int countContainersInDocker(final String imageName) throws Exception { + return countContainersInDocker(imageName, null); + } /** * Counts the number of instances currently running in Docker that are using - * the specified image. + * the specified image and template.
+ * Returns all containers matching the given filter parameters. + * *

* WARNING: This method can be slow so it should be called sparingly. * * @param imageName - * If null, then all instances belonging to this Jenkins instance - * are counted. Otherwise, only those started with the specified - * image are counted. + * filter for imageName. If null, no filter is active for imageName. + * @param templateName + * filter for templateName. If null, no filter is active for templateName. + * * @return The number of containers. * @throws Exception if anything went wrong. */ - public int countContainersInDocker(final String imageName) throws Exception { + public int countContainersInDocker(final String imageName, final String templateName) throws Exception { final Map labelFilter = new HashMap<>(); labelFilter.put( DockerContainerLabelKeys.JENKINS_INSTANCE_ID, @@ -623,10 +636,14 @@ public int countContainersInDocker(final String imageName) throws Exception { if (imageName != null) { labelFilter.put(DockerContainerLabelKeys.CONTAINER_IMAGE, imageName); } - final List containers; + if (templateName != null) { + labelFilter.put(DockerContainerLabelKeys.TEMPLATE_NAME, templateName); + } + final List containers; try (final DockerClient client = dockerApi.getClient()) { containers = client.listContainersCmd().withLabelFilter(labelFilter).exec(); } + final int count = containers.size(); return count; } @@ -636,6 +653,7 @@ public int countContainersInDocker(final String imageName) throws Exception { */ private boolean canAddProvisionedAgent(DockerTemplate t) throws Exception { final String templateImage = t.getImage(); + final String templateName = t.getName(); final int templateContainerCap = t.instanceCap; final int cloudContainerCap = getContainerCap(); @@ -643,7 +661,7 @@ private boolean canAddProvisionedAgent(DockerTemplate t) throws Exception { final boolean haveTemplateContainerCap = templateContainerCap > 0 && templateContainerCap != Integer.MAX_VALUE; final int estimatedTotalAgents; if (haveCloudContainerCap) { - final int totalContainersInCloud = countContainersInDocker(null); + final int totalContainersInCloud = countContainersInDocker(null, null); final int containersInProgress = countContainersInProgress(); estimatedTotalAgents = totalContainersInCloud + containersInProgress; if (estimatedTotalAgents >= cloudContainerCap) { @@ -659,7 +677,7 @@ private boolean canAddProvisionedAgent(DockerTemplate t) throws Exception { } final int estimatedTemplateAgents; if (haveTemplateContainerCap) { - final int totalContainersOfThisTemplateInCloud = countContainersInDocker(templateImage); + final int totalContainersOfThisTemplateInCloud = countContainersInDocker(templateImage, templateName); final int containersInProgress = countContainersInProgress(t); estimatedTemplateAgents = totalContainersOfThisTemplateInCloud + containersInProgress; if (estimatedTemplateAgents >= templateContainerCap) { diff --git a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html index c1fbde80c..64236e40f 100644 --- a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html +++ b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html @@ -4,4 +4,8 @@ Jenkins will append a unique ID to this name in order to create individual node names.

If blank or just whitespace, a default of "docker" will be used. +

+ When using the same docker image in multiple docker agent templates, make sure to set an individual name for each template.
+ This is needed for capping by number of container instance by template to work correctly. +

diff --git a/src/test/java/io/jenkins/docker/connector/DockerComputerConnectorTest.java b/src/test/java/io/jenkins/docker/connector/DockerComputerConnectorTest.java index 355488dbd..fe41ad2d0 100644 --- a/src/test/java/io/jenkins/docker/connector/DockerComputerConnectorTest.java +++ b/src/test/java/io/jenkins/docker/connector/DockerComputerConnectorTest.java @@ -148,7 +148,7 @@ private boolean dockerIsStillBusy() throws Exception { return true; } } - final int containersInDocker = cloud.countContainersInDocker(null); + final int containersInDocker = cloud.countContainersInDocker(null, null); if (containersInDocker > 0) { return true; } From 883ede27474b0e256e9b286b74e3d38471d921f3 Mon Sep 17 00:00:00 2001 From: Fabian Wunsch Date: Fri, 2 Dec 2022 14:44:08 +0100 Subject: [PATCH 2/3] added missing close p-tag --- .../nirima/jenkins/plugins/docker/DockerTemplate/help-name.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html index 64236e40f..ee9598af2 100644 --- a/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html +++ b/src/main/resources/com/nirima/jenkins/plugins/docker/DockerTemplate/help-name.html @@ -4,6 +4,7 @@ Jenkins will append a unique ID to this name in order to create individual node names.

If blank or just whitespace, a default of "docker" will be used. +

When using the same docker image in multiple docker agent templates, make sure to set an individual name for each template.
This is needed for capping by number of container instance by template to work correctly. From 7daa0c59c49d9df314a34b0f5b36aaba6e0d7f22 Mon Sep 17 00:00:00 2001 From: Carsten Pfeiffer Date: Thu, 1 Jun 2023 13:55:34 +0200 Subject: [PATCH 3/3] Apply spotless --- .../nirima/jenkins/plugins/docker/DockerCloud.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java b/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java index e88ca4d01..faa531fa2 100644 --- a/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java +++ b/src/main/java/com/nirima/jenkins/plugins/docker/DockerCloud.java @@ -602,21 +602,21 @@ public synchronized void removeTemplate(DockerTemplate t) { templates.remove(t); } } - + /** * @deprecated use countContainersInDocker(String, String) instead * @see DockerCloud#countContainersInDocker(String, String) */ @Deprecated public int countContainersInDocker(final String imageName) throws Exception { - return countContainersInDocker(imageName, null); + return countContainersInDocker(imageName, null); } /** * Counts the number of instances currently running in Docker that are using * the specified image and template.
* Returns all containers matching the given filter parameters. - * + * *

* WARNING: This method can be slow so it should be called sparingly. * @@ -637,13 +637,13 @@ public int countContainersInDocker(final String imageName, final String template labelFilter.put(DockerContainerLabelKeys.CONTAINER_IMAGE, imageName); } if (templateName != null) { - labelFilter.put(DockerContainerLabelKeys.TEMPLATE_NAME, templateName); + labelFilter.put(DockerContainerLabelKeys.TEMPLATE_NAME, templateName); } final List containers; try (final DockerClient client = dockerApi.getClient()) { containers = client.listContainersCmd().withLabelFilter(labelFilter).exec(); } - + final int count = containers.size(); return count; } @@ -677,7 +677,7 @@ private boolean canAddProvisionedAgent(DockerTemplate t) throws Exception { } final int estimatedTemplateAgents; if (haveTemplateContainerCap) { - final int totalContainersOfThisTemplateInCloud = countContainersInDocker(templateImage, templateName); + final int totalContainersOfThisTemplateInCloud = countContainersInDocker(templateImage, templateName); final int containersInProgress = countContainersInProgress(t); estimatedTemplateAgents = totalContainersOfThisTemplateInCloud + containersInProgress; if (estimatedTemplateAgents >= templateContainerCap) {