|
28 | 28 | import org.apache.commons.codec.binary.Base64;
|
29 | 29 | import org.apache.commons.lang.StringUtils;
|
30 | 30 | import org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateMap;
|
| 31 | +import org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default; |
| 32 | +import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention; |
31 | 33 | import org.jenkinsci.plugins.plaincredentials.FileCredentials;
|
32 | 34 | import org.jenkinsci.plugins.plaincredentials.StringCredentials;
|
33 | 35 | import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
|
43 | 45 | import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
|
44 | 46 | import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
|
45 | 47 | import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
|
46 |
| -import com.ctc.wstx.util.StringUtil; |
47 |
| -import com.google.common.base.Preconditions; |
48 | 48 | import com.google.common.base.Strings;
|
49 | 49 | import com.google.common.collect.ImmutableMap;
|
50 | 50 |
|
|
55 | 55 | import hudson.init.InitMilestone;
|
56 | 56 | import hudson.init.Initializer;
|
57 | 57 | import hudson.model.Descriptor;
|
| 58 | +import hudson.model.DescriptorVisibilityFilter; |
58 | 59 | import hudson.model.Label;
|
59 | 60 | import hudson.security.ACL;
|
60 | 61 | import hudson.slaves.Cloud;
|
@@ -115,6 +116,8 @@ public class KubernetesCloud extends Cloud {
|
115 | 116 |
|
116 | 117 | private transient KubernetesClient client;
|
117 | 118 | private int maxRequestsPerHost;
|
| 119 | + @CheckForNull |
| 120 | + private PodRetention podRetention = PodRetention.getKubernetesCloudDefault(); |
118 | 121 |
|
119 | 122 | @DataBoundConstructor
|
120 | 123 | public KubernetesCloud(String name) {
|
@@ -143,6 +146,7 @@ public KubernetesCloud(@NonNull String name, @NonNull KubernetesCloud source) {
|
143 | 146 | this.containerCap = source.containerCap;
|
144 | 147 | this.retentionTimeout = source.retentionTimeout;
|
145 | 148 | this.connectTimeout = source.connectTimeout;
|
| 149 | + this.podRetention = source.podRetention; |
146 | 150 | }
|
147 | 151 |
|
148 | 152 | @Deprecated
|
@@ -251,10 +255,12 @@ public String getJenkinsUrl() {
|
251 | 255 | }
|
252 | 256 |
|
253 | 257 | @DataBoundSetter
|
| 258 | + @Deprecated |
254 | 259 | public void setCapOnlyOnAlivePods(boolean capOnlyOnAlivePods) {
|
255 | 260 | this.capOnlyOnAlivePods = capOnlyOnAlivePods;
|
256 | 261 | }
|
257 | 262 |
|
| 263 | + @Deprecated |
258 | 264 | public boolean isCapOnlyOnAlivePods() {
|
259 | 265 | return capOnlyOnAlivePods;
|
260 | 266 | }
|
@@ -378,6 +384,26 @@ public void setConnectTimeout(int connectTimeout) {
|
378 | 384 | this.connectTimeout = connectTimeout;
|
379 | 385 | }
|
380 | 386 |
|
| 387 | + /** |
| 388 | + * Gets the global pod retention policy for the plugin. |
| 389 | + */ |
| 390 | + public PodRetention getPodRetention() { |
| 391 | + return this.podRetention; |
| 392 | + } |
| 393 | + |
| 394 | + /** |
| 395 | + * Set the global pod retention policy for the plugin. |
| 396 | + * |
| 397 | + * @param podRetention the pod retention policy for the plugin. |
| 398 | + */ |
| 399 | + @DataBoundSetter |
| 400 | + public void setPodRetention(PodRetention podRetention) { |
| 401 | + if (podRetention == null || podRetention instanceof Default) { |
| 402 | + podRetention = PodRetention.getKubernetesCloudDefault(); |
| 403 | + } |
| 404 | + this.podRetention = podRetention; |
| 405 | + } |
| 406 | + |
381 | 407 | /**
|
382 | 408 | * Connects to Kubernetes.
|
383 | 409 | *
|
@@ -454,42 +480,30 @@ private boolean addProvisionedSlave(@Nonnull PodTemplate template, @CheckForNull
|
454 | 480 | }
|
455 | 481 |
|
456 | 482 | PodList slaveList = client.pods().inNamespace(templateNamespace).withLabels(getLabels()).list();
|
457 |
| - List<Pod> slaveListItems = slaveList.getItems(); |
| 483 | + List<Pod> allActiveSlavePods = slaveList.getItems().stream() |
| 484 | + .filter(x -> x.getStatus().getPhase().toLowerCase().matches("(running|pending)")) |
| 485 | + .collect(Collectors.toList()); |
458 | 486 |
|
459 | 487 | Map<String, String> labelsMap = new HashMap<>(this.getLabels());
|
460 | 488 | labelsMap.putAll(template.getLabelsMap());
|
461 |
| - PodList namedList = client.pods().inNamespace(templateNamespace).withLabels(labelsMap).list(); |
462 |
| - List<Pod> namedListItems = namedList.getItems(); |
463 |
| - |
464 |
| - if (this.isCapOnlyOnAlivePods()) { |
465 |
| - slaveListItems = slaveListItems.stream() |
466 |
| - .filter(x -> x.getStatus() |
467 |
| - .getPhase().toLowerCase() |
468 |
| - .matches("(running|pending)")) |
469 |
| - .collect(Collectors.toList()); |
470 |
| - } |
471 |
| - |
472 |
| - if (template.isCapOnlyOnAlivePods()) { |
473 |
| - namedListItems = namedListItems.stream() |
474 |
| - .filter(x -> x.getStatus() |
475 |
| - .getPhase().toLowerCase() |
476 |
| - .matches("(running|pending)")) |
477 |
| - .collect(Collectors.toList()); |
478 |
| - } |
| 489 | + PodList templateSlaveList = client.pods().inNamespace(templateNamespace).withLabels(labelsMap).list(); |
| 490 | + List<Pod> activeTemplateSlavePods = templateSlaveList.getItems().stream() |
| 491 | + .filter(x -> x.getStatus().getPhase().toLowerCase().matches("(running|pending)")) |
| 492 | + .collect(Collectors.toList()); |
479 | 493 |
|
480 |
| - if (slaveListItems != null && containerCap <= slaveListItems.size()) { |
| 494 | + if (allActiveSlavePods != null && containerCap <= allActiveSlavePods.size()) { |
481 | 495 | LOGGER.log(Level.INFO,
|
482 |
| - "Total container cap of {0} reached, not provisioning: {1} running or errored in namespace {2} with Kubernetes labels {3}", |
483 |
| - new Object[] { containerCap, slaveListItems.size(), templateNamespace, getLabels() }); |
| 496 | + "Total container cap of {0} reached, not provisioning: {1} running or pending in namespace {2} with Kubernetes labels {3}", |
| 497 | + new Object[] { containerCap, allActiveSlavePods.size(), templateNamespace, getLabels() }); |
484 | 498 | return false;
|
485 | 499 | }
|
486 | 500 |
|
487 |
| - if (namedListItems != null && slaveListItems != null && template.getInstanceCap() <= namedListItems.size()) { |
| 501 | + if (activeTemplateSlavePods != null && allActiveSlavePods != null && template.getInstanceCap() <= activeTemplateSlavePods.size()) { |
488 | 502 | LOGGER.log(Level.INFO,
|
489 |
| - "Template instance cap of {0} reached for template {1}, not provisioning: {2} running or errored in namespace {3} with label \"{4}\" and Kubernetes labels {5}", |
490 |
| - new Object[] { template.getInstanceCap(), template.getName(), slaveListItems.size(), |
| 503 | + "Template instance cap of {0} reached for template {1}, not provisioning: {2} running or pending in namespace {3} with label \"{4}\" and Kubernetes labels {5}", |
| 504 | + new Object[] { template.getInstanceCap(), template.getName(), allActiveSlavePods.size(), |
491 | 505 | templateNamespace, label == null ? "" : label.toString(), labelsMap });
|
492 |
| - return false; // maxed out |
| 506 | + return false; |
493 | 507 | }
|
494 | 508 | return true;
|
495 | 509 | }
|
@@ -652,6 +666,24 @@ public FormValidation doCheckMaxRequestsPerHostStr(@QueryParameter String value)
|
652 | 666 | return FormValidation.error("Please supply an integer");
|
653 | 667 | }
|
654 | 668 | }
|
| 669 | + |
| 670 | + public List<Descriptor<PodRetention>> getAllowedPodRetentions() { |
| 671 | + Jenkins jenkins = Jenkins.getInstanceOrNull(); |
| 672 | + if (jenkins == null) { |
| 673 | + return new ArrayList<>(0); |
| 674 | + } |
| 675 | + return DescriptorVisibilityFilter.apply(this, jenkins.getDescriptorList(PodRetention.class)); |
| 676 | + } |
| 677 | + |
| 678 | + @SuppressWarnings("rawtypes") |
| 679 | + public Descriptor getDefaultPodRetention() { |
| 680 | + Jenkins jenkins = Jenkins.getInstanceOrNull(); |
| 681 | + if (jenkins == null) { |
| 682 | + return null; |
| 683 | + } |
| 684 | + return jenkins.getDescriptor(PodRetention.getKubernetesCloudDefault().getClass()); |
| 685 | + } |
| 686 | + |
655 | 687 | }
|
656 | 688 |
|
657 | 689 | @Override
|
|
0 commit comments