Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow customization of NodeProvisioner.PlannedNode using extension point #298

Merged
merged 2 commits into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import hudson.Util;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.model.Computer;
import hudson.model.Descriptor;
import hudson.model.Label;
import hudson.model.Node;
Expand Down Expand Up @@ -405,9 +404,7 @@ public synchronized Collection<NodeProvisioner.PlannedNode> provision(@CheckForN
if (!addProvisionedSlave(t, label)) {
break;
}

r.add(new NodeProvisioner.PlannedNode(t.getDisplayName(), Computer.threadPoolForRemoting
.submit(new ProvisioningCallback(this, t, label)), 1));
r.add(PlannedNodeBuilderFactory.createInstance().cloud(this).template(t).label(label).build());
}
if (r.size() > 0) {
// Already found a matching template
Expand Down Expand Up @@ -487,6 +484,15 @@ public PodTemplate getTemplate(@CheckForNull Label label) {
return PodTemplateUtils.getTemplateByLabel(label, getAllTemplates());
}

/**
* Unwraps the given pod template.
* @param podTemplate the pod template to unwrap.
* @return the unwrapped pod template
*/
public PodTemplate getUnwrappedTemplate(PodTemplate podTemplate) {
return PodTemplateUtils.unwrap(podTemplate, getDefaultsProviderTemplate(), getAllTemplates());
}

/**
* Gets all PodTemplates that have the matching {@link Label}.
* @param label label to look for in templates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.jenkinsci.plugins.durabletask.executors.Messages;
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
import org.jvnet.localizer.Localizable;
Expand All @@ -29,6 +30,8 @@
import hudson.model.TaskListener;
import hudson.slaves.AbstractCloudSlave;
import hudson.slaves.Cloud;
import hudson.slaves.CloudRetentionStrategy;
import hudson.slaves.ComputerLauncher;
import hudson.slaves.OfflineCause;
import hudson.slaves.RetentionStrategy;
import io.fabric8.kubernetes.client.KubernetesClient;
Expand Down Expand Up @@ -62,7 +65,7 @@ public PodTemplate getTemplate() {
}

/**
* @deprecated Use {@link #KubernetesSlave(PodTemplate, String, String, String, RetentionStrategy)} instead.
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesCloud cloud, String labelStr)
Expand All @@ -72,7 +75,7 @@ public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesC
}

/**
* @deprecated Use {@link #KubernetesSlave(PodTemplate, String, String, String, RetentionStrategy)} instead.
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesCloud cloud, Label label)
Expand All @@ -81,7 +84,7 @@ public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesC
}

/**
* @deprecated Use {@link #KubernetesSlave(PodTemplate, String, String, String, RetentionStrategy)} instead.
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesCloud cloud, String labelStr,
Expand All @@ -90,18 +93,27 @@ public KubernetesSlave(PodTemplate template, String nodeDescription, KubernetesC
this(template, nodeDescription, cloud.name, labelStr, rs);
}

@DataBoundConstructor
/**
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
@DataBoundConstructor // make stapler happy. Not actually used.
public KubernetesSlave(PodTemplate template, String nodeDescription, String cloudName, String labelStr,
RetentionStrategy rs)
throws Descriptor.FormException, IOException {
this(getSlaveName(template), template, nodeDescription, cloudName, labelStr, new KubernetesLauncher(), rs);
}

super(getSlaveName(template),
protected KubernetesSlave(String name, PodTemplate template, String nodeDescription, String cloudName, String labelStr,
ComputerLauncher computerLauncher, RetentionStrategy rs)
throws Descriptor.FormException, IOException {
super(name,
nodeDescription,
template.getRemoteFs(),
1,
template.getNodeUsageMode() != null ? template.getNodeUsageMode() : Node.Mode.NORMAL,
labelStr == null ? null : labelStr,
new KubernetesLauncher(),
computerLauncher,
rs,
template.getNodeProperties());

Expand Down Expand Up @@ -257,6 +269,118 @@ public int hashCode() {
return result;
}

/**
* Returns a new {@link Builder} instance.
* @return a new {@link Builder} instance.
*/
public static Builder builder() {
return new Builder();
}

/**
* Builds a {@link KubernetesSlave} instance.
*/
public static class Builder {
private String name;
private String nodeDescription;
private PodTemplate podTemplate;
private KubernetesCloud cloud;
private String label;
private ComputerLauncher computerLauncher;
private RetentionStrategy retentionStrategy;

/**
* @param name The name of the future {@link KubernetesSlave}
* @return the current instance for method chaining
*/
public Builder name(String name) {
this.name = name;
return this;
}

/**
* @param nodeDescription The node description of the future {@link KubernetesSlave}
* @return the current instance for method chaining
*/
public Builder nodeDescription(String nodeDescription) {
this.nodeDescription = nodeDescription;
return this;
}

/**
* @param podTemplate The pod template the future {@link KubernetesSlave} has been created from
* @return the current instance for method chaining
*/
public Builder podTemplate(PodTemplate podTemplate) {
this.podTemplate = podTemplate;
return this;
}

/**
* @param cloud The cloud that is provisioning the {@link KubernetesSlave} instance.
* @return the current instance for method chaining
*/
public Builder cloud(KubernetesCloud cloud) {
this.cloud = cloud;
return this;
}

/**
* @param label The label the {@link KubernetesSlave} has.
* @return the current instance for method chaining
*/
public Builder label(String label) {
this.label = label;
return this;
}

/**
* @param computerLauncher The computer launcher to use to launch the {@link KubernetesSlave} instance.
* @return the current instance for method chaining
*/
public Builder computerLauncher(ComputerLauncher computerLauncher) {
this.computerLauncher = computerLauncher;
return this;
}

/**
* @param retentionStrategy The retention strategy to use for the {@link KubernetesSlave} instance.
* @return the current instance for method chaining
*/
public Builder retentionStrategy(RetentionStrategy retentionStrategy) {
this.retentionStrategy = retentionStrategy;
return this;
}

private RetentionStrategy determineRetentionStrategy() {
if (podTemplate.getIdleMinutes() == 0) {
return new OnceRetentionStrategy(cloud.getRetentionTimeout());
} else {
return new CloudRetentionStrategy(podTemplate.getIdleMinutes());
}
}

/**
* Builds the resulting {@link KubernetesSlave} instance.
* @return an initialized {@link KubernetesSlave} instance.
* @throws IOException
* @throws Descriptor.FormException
*/
public KubernetesSlave build() throws IOException, Descriptor.FormException {
Validate.notNull(podTemplate);
Validate.notNull(cloud);
return new KubernetesSlave(
name == null ? getSlaveName(podTemplate) : name,
podTemplate,
nodeDescription == null ? podTemplate.getName() : nodeDescription,
cloud.name,
label == null ? podTemplate.getLabel() : label,
computerLauncher == null ? new KubernetesLauncher() : computerLauncher,
retentionStrategy == null ? determineRetentionStrategy() : retentionStrategy);
}
}


@Extension
public static final class DescriptorImpl extends SlaveDescriptor {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.csanchez.jenkins.plugins.kubernetes;

import hudson.model.Label;
import hudson.slaves.NodeProvisioner;

/**
* A builder of {@link hudson.slaves.NodeProvisioner.PlannedNode} implementations for Kubernetes.
* Can be subclassed to provide alternative implementations of {@link hudson.slaves.NodeProvisioner.PlannedNode}.
*/
public abstract class PlannedNodeBuilder {
private KubernetesCloud cloud;
private PodTemplate template;
private Label label;
private int numExecutors = 1;

/**
* Returns the {@link KubernetesCloud}.
* @return the {@link KubernetesCloud}.
*/
public KubernetesCloud getCloud() {
return cloud;
}

/**
* Returns the {@link PodTemplate}.
* @return
*/
public PodTemplate getTemplate() {
return template;
}

public Label getLabel() {
return label;
}

public int getNumExecutors() {
return numExecutors;
}

/**
* @param cloud the {@link KubernetesCloud} instance to use.
* @return the current builder.
*/
public PlannedNodeBuilder cloud(KubernetesCloud cloud) {
this.cloud = cloud;
return this;
}

/**
* @param template the {@link PodTemplate} instance to use.
* @return the current builder.
*/
public PlannedNodeBuilder template(PodTemplate template) {
this.template = template;
return this;
}

/**
* @param label the {@link Label} to use.
* @return the current builder.
*/
public PlannedNodeBuilder label(Label label) {
this.label = label;
return this;
}

/**
* @param numExecutors the number of executors.
* @return the current builder.
*/
public PlannedNodeBuilder numExecutors(int numExecutors) {
this.numExecutors = numExecutors;
return this;
}

/**
* Builds the {@link hudson.slaves.NodeProvisioner.PlannedNode} instance based on the given inputs.
* @return a {@link hudson.slaves.NodeProvisioner.PlannedNode} configured from this builder.
*/
public abstract NodeProvisioner.PlannedNode build();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.csanchez.jenkins.plugins.kubernetes;

import hudson.ExtensionList;
import hudson.ExtensionPoint;

/**
* A factory of {@link PlannedNodeBuilder} instances.
*/
public abstract class PlannedNodeBuilderFactory implements ExtensionPoint {
/**
* Returns all registered implementations of {@link PlannedNodeBuilderFactory}.
* @return all registered implementations of {@link PlannedNodeBuilderFactory}.
*/
public static ExtensionList<PlannedNodeBuilderFactory> all() {
return ExtensionList.lookup(PlannedNodeBuilderFactory.class);
}

/**
* Returns a new instance of {@link PlannedNodeBuilder}.
* @return a new instance of {@link PlannedNodeBuilder}.
*/
public static PlannedNodeBuilder createInstance() {
for (PlannedNodeBuilderFactory factory: all()) {
PlannedNodeBuilder plannedNodeBuilder = factory.newInstance();
if (plannedNodeBuilder != null) {
return plannedNodeBuilder;
}
}
return new StandardPlannedNodeBuilder();
}

/**
* Creates a new instance of {@link PlannedNodeBuilder}.
* @return a new instance of {@link PlannedNodeBuilder}.
*/
public abstract PlannedNodeBuilder newInstance();
}
Loading