Skip to content

Commit 3a18554

Browse files
authored
Merge pull request #2844 from hareldev/add-409-clusterresourcequotas
Broaden the 409 handling for OpenShift ClusterResourceQuota
2 parents 62200f8 + 16707d8 commit 3a18554

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ public synchronized void launch(SlaveComputer computer, TaskListener listener) {
177177
namespace,
178178
pod.getMetadata().getName(),
179179
e.getMessage());
180-
} else if (httpCode == 409
181-
&& e.getMessage().contains("Operation cannot be fulfilled on resourcequotas")) {
180+
} else if (isResourceQuotaUpdateConflict(httpCode, e.getMessage())) {
182181
// See: https://github.com/kubernetes/kubernetes/issues/67761 ; A retry usually works.
182+
// OpenShift ClusterResourceQuota conflicts use clusterresourcequotas.quota.openshift.io.
183183
node.getRunListener()
184184
.getLogger()
185185
.printf(
@@ -391,6 +391,19 @@ private void logLastLines(
391391
}
392392
}
393393

394+
/**
395+
* Detects transient quota update conflicts during pod creation.
396+
* These occur when concurrent pod creations race to update ResourceQuota or OpenShift ClusterResourceQuota.
397+
*
398+
* @see <a href="https://github.com/kubernetes/kubernetes/issues/67761">kubernetes#67761</a>
399+
*/
400+
static boolean isResourceQuotaUpdateConflict(int httpCode, @CheckForNull String message) {
401+
return httpCode == 409
402+
&& message != null
403+
&& message.contains("Operation cannot be fulfilled on")
404+
&& message.contains("resourcequotas");
405+
}
406+
394407
/**
395408
* The last problem that occurred, if any.
396409
* @return
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.csanchez.jenkins.plugins.kubernetes;
2+
3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertTrue;
5+
6+
import org.junit.Test;
7+
import org.jvnet.hudson.test.WithoutJenkins;
8+
9+
public class KubernetesLauncherTest {
10+
11+
private static final String K8S_RESOURCE_QUOTA_CONFLICT =
12+
"Operation cannot be fulfilled on resourcequotas \"compute-resources\": the object has been modified; please apply your changes to the latest version and try again";
13+
14+
private static final String OPENSHIFT_CLUSTER_RESOURCE_QUOTA_CONFLICT =
15+
"Operation cannot be fulfilled on clusterresourcequotas.quota.openshift.io \"dno--notterminating\": the object has been modified; please apply your changes to the latest version and try again";
16+
17+
@WithoutJenkins
18+
@Test
19+
public void isResourceQuotaUpdateConflict_kubernetesResourceQuota() {
20+
assertTrue(KubernetesLauncher.isResourceQuotaUpdateConflict(409, K8S_RESOURCE_QUOTA_CONFLICT));
21+
}
22+
23+
@WithoutJenkins
24+
@Test
25+
public void isResourceQuotaUpdateConflict_openshiftClusterResourceQuota() {
26+
assertTrue(KubernetesLauncher.isResourceQuotaUpdateConflict(409, OPENSHIFT_CLUSTER_RESOURCE_QUOTA_CONFLICT));
27+
}
28+
29+
@WithoutJenkins
30+
@Test
31+
public void isResourceQuotaUpdateConflict_not409() {
32+
assertFalse(KubernetesLauncher.isResourceQuotaUpdateConflict(403, K8S_RESOURCE_QUOTA_CONFLICT));
33+
}
34+
35+
@WithoutJenkins
36+
@Test
37+
public void isResourceQuotaUpdateConflict_nullMessage() {
38+
assertFalse(KubernetesLauncher.isResourceQuotaUpdateConflict(409, null));
39+
}
40+
41+
@WithoutJenkins
42+
@Test
43+
public void isResourceQuotaUpdateConflict_unrelated409() {
44+
assertFalse(KubernetesLauncher.isResourceQuotaUpdateConflict(409, "pods \"my-pod\" already exists"));
45+
}
46+
}

0 commit comments

Comments
 (0)