package org.csanchez.jenkins.plugins.kubernetes.pipeline; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud; import org.csanchez.jenkins.plugins.kubernetes.PodTemplate; import org.jenkinsci.plugins.workflow.steps.AbstractStepExecutionImpl; import org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback; import org.jenkinsci.plugins.workflow.steps.StepContext; import com.google.common.base.Strings; import hudson.AbortException; import hudson.model.Run; import hudson.slaves.Cloud; import jenkins.model.Jenkins; public class PodTemplateStepExecution extends AbstractStepExecutionImpl { private static final Logger LOGGER = Logger.getLogger(PodTemplateStepExecution.class.getName()); private static final long serialVersionUID = -6139090518333729333L; private static final transient String NAME_FORMAT = "%s-%s"; private final PodTemplateStep step; PodTemplateStepExecution(PodTemplateStep step, StepContext context) { super(context); this.step = step; } @Override public boolean start() throws Exception { Cloud cloud = Jenkins.getInstance().getCloud(step.getCloud()); if (cloud == null) { throw new AbortException(String.format("Cloud does not exist: %s", step.getCloud())); } if (!(cloud instanceof KubernetesCloud)) { throw new AbortException(String.format("Cloud is not a Kubernetes cloud: %s (%s)", step.getCloud(), cloud.getClass().getName())); } KubernetesCloud kubernetesCloud = (KubernetesCloud) cloud; String uuid = UUID.randomUUID().toString().replaceAll("-", ""); String name = String.format(NAME_FORMAT, step.getName(), uuid); PodTemplateAction action = new PodTemplateAction(getContext().get(Run.class)); PodTemplate newTemplate = new PodTemplate(); newTemplate.setName(name); newTemplate.setInheritFrom(!Strings.isNullOrEmpty( action.getParentTemplates()) ? action.getParentTemplates() : step.getInheritFrom()); newTemplate.setInstanceCap(step.getInstanceCap()); newTemplate.setLabel(step.getLabel()); newTemplate.setVolumes(step.getVolumes()); newTemplate.setCustomWorkspaceVolumeEnabled(step.getWorkspaceVolume() != null); newTemplate.setWorkspaceVolume(step.getWorkspaceVolume()); newTemplate.setContainers(step.getContainers()); newTemplate.setNodeSelector(step.getNodeSelector()); newTemplate.setServiceAccount(step.getServiceAccount()); newTemplate.setAnnotations(step.getAnnotations()); kubernetesCloud.addTemplate(newTemplate); getContext().newBodyInvoker().withContext(step).withCallback(new PodTemplateCallback(newTemplate)).start(); action.push(step.getLabel()); return false; } @Override public void stop(Throwable cause) throws Exception { new PodTemplateAction(getContext().get(Run.class)).pop(); } private class PodTemplateCallback extends BodyExecutionCallback.TailCall { private static final long serialVersionUID = 6043919968776851324L; private final PodTemplate podTemplate; private PodTemplateCallback(PodTemplate podTemplate) { this.podTemplate = podTemplate; } @Override /** * Remove the template after step is done */ protected void finished(StepContext context) throws Exception { Cloud cloud = Jenkins.getInstance().getCloud(step.getCloud()); if (cloud == null) { LOGGER.log(Level.FINE, "Cloud {0} no longer exists, cannot delete pod template {1}", new Object[] { step.getCloud(), podTemplate.getName() }); return; } if (cloud instanceof KubernetesCloud) { KubernetesCloud kubernetesCloud = (KubernetesCloud) cloud; kubernetesCloud.removeTemplate(podTemplate); } } } }