diff --git a/pom.xml b/pom.xml index b00193d0c6..684527b2fb 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,12 @@ 4.5.1 + + org.apache.commons + commons-lang3 + 3.5 + + org.jenkins-ci.plugins durable-task diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java index d89be62fd2..fa40d87cfe 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java @@ -54,7 +54,9 @@ import hudson.model.Node; import hudson.security.ACL; import hudson.slaves.Cloud; +import hudson.slaves.CloudRetentionStrategy; import hudson.slaves.NodeProvisioner; +import hudson.slaves.RetentionStrategy; import hudson.util.FormValidation; import hudson.util.ListBoxModel; import io.fabric8.kubernetes.api.model.Container; @@ -73,6 +75,7 @@ import jenkins.model.Jenkins; import jenkins.model.JenkinsLocationConfiguration; import static org.csanchez.jenkins.plugins.kubernetes.PodTemplateUtils.substituteEnv; +import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy; /** * Kubernetes cloud provider. @@ -539,9 +542,14 @@ public ProvisioningCallback(KubernetesCloud cloud, PodTemplate t, Label label) { public Node call() throws Exception { KubernetesSlave slave = null; + RetentionStrategy retentionStrategy = null; try { - - slave = new KubernetesSlave(t, t.getName(), cloud, t.getLabel()); + if (t.getIdleMinutes() == 0) { + retentionStrategy = new OnceRetentionStrategy(cloud.getRetentionTimeout()); + } else { + retentionStrategy = new CloudRetentionStrategy(t.getIdleMinutes()); + } + slave = new KubernetesSlave(t, t.getName(), cloud, t.getLabel(), retentionStrategy); Jenkins.getActiveInstance().addNode(slave); Pod pod = getPodTemplate(slave, label); diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java index 8a4722580a..158a1b8a46 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java @@ -19,8 +19,8 @@ import hudson.model.TaskListener; import hudson.slaves.AbstractCloudSlave; import hudson.slaves.JNLPLauncher; -import hudson.slaves.NodeProperty; import hudson.slaves.OfflineCause; +import hudson.slaves.RetentionStrategy; import io.fabric8.kubernetes.api.model.DoneablePod; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.client.KubernetesClient; @@ -44,34 +44,31 @@ public class KubernetesSlave extends AbstractCloudSlave { private transient final KubernetesCloud cloud; - @DataBoundConstructor public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesCloud cloud, String labelStr) throws Descriptor.FormException, IOException { - super(getSlaveName(template), - nodeDescription, - template.getRemoteFs(), - 1, - Node.Mode.NORMAL, - labelStr == null ? null : labelStr, - new JNLPLauncher(), - new OnceRetentionStrategy(cloud.getRetentionTimeout()), - template.getNodeProperties()); - // this.pod = pod; - this.cloud = cloud; + this(template, nodeDescription, cloud, labelStr, new OnceRetentionStrategy(cloud.getRetentionTimeout())); } @Deprecated public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesCloud cloud, Label label) throws Descriptor.FormException, IOException { + this(template, nodeDescription, cloud, label.toString(), new OnceRetentionStrategy(cloud.getRetentionTimeout())) ; + } + + @DataBoundConstructor + public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesCloud cloud, String labelStr, + RetentionStrategy rs) + throws Descriptor.FormException, IOException { + super(getSlaveName(template), nodeDescription, template.getRemoteFs(), 1, Node.Mode.NORMAL, - label == null ? null : label.toString(), + labelStr == null ? null : labelStr, new JNLPLauncher(), - new OnceRetentionStrategy(cloud.getRetentionTimeout()), + rs, template.getNodeProperties()); // this.pod = pod; @@ -114,7 +111,7 @@ protected void _terminate(TaskListener listener) throws IOException, Interrupted computer.disconnect(OfflineCause.create(new Localizable(HOLDER, "offline"))); LOGGER.log(Level.INFO, "Disconnected computer {0}", name); } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Failure to terminate instance for slave " + name, e); + LOGGER.log(Level.SEVERE, "Failed to terminate pod for slave " + name, e); } } diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java index 35eca3af79..1bdde5d609 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java @@ -24,6 +24,8 @@ import hudson.model.Label; import hudson.model.labels.LabelAtom; +import org.apache.commons.lang3.StringUtils; + /** * Kubernetes Pod Template * @@ -51,6 +53,8 @@ public class PodTemplate extends AbstractDescribableImpl { private int instanceCap = Integer.MAX_VALUE; + private int idleMinutes; + private String label; private String serviceAccount; @@ -188,7 +192,7 @@ public int getInstanceCap() { @DataBoundSetter public void setInstanceCapStr(String instanceCapStr) { - if ("".equals(instanceCapStr)) { + if (StringUtils.isBlank(instanceCapStr)) { setInstanceCap(Integer.MAX_VALUE); } else { setInstanceCap(Integer.parseInt(instanceCapStr)); @@ -203,6 +207,31 @@ public String getInstanceCapStr() { } } + public void setIdleMinutes(int i) { + this.idleMinutes = i; + } + + public int getIdleMinutes() { + return idleMinutes; + } + + @DataBoundSetter + public void setIdleMinutesStr(String idleMinutes) { + if (StringUtils.isBlank(idleMinutes)) { + setIdleMinutes(0); + } else { + setIdleMinutes(Integer.parseInt(idleMinutes)); + } + } + + public String getIdleMinutesStr() { + if (getIdleMinutes() == 0) { + return ""; + } else { + return String.valueOf(idleMinutes); + } + } + public Set getLabelSet() { return Label.parse(label); } diff --git a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/config.jelly b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/config.jelly index 8f585696b5..978178a206 100644 --- a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/config.jelly +++ b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/config.jelly @@ -36,6 +36,10 @@ + + + +