Skip to content

Commit

Permalink
Extra support for
Browse files Browse the repository at this point in the history
- DNS setting
- Tagging after use
- Pushing after use

Token Macro for the container ID

Builder and publisher to start / stop containers as a part of the build.

Signed-off-by: Nigel Magnay <[email protected]>
  • Loading branch information
magnayn committed Jan 30, 2014
1 parent 8bac0b2 commit 87d670e
Show file tree
Hide file tree
Showing 24 changed files with 698 additions and 26 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
<artifactId>ssh-slaves</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>token-macro</artifactId>
<version>1.7</version>
<optional>true</optional>
</dependency>
<!--<dependency>-->
<!--<groupId>org.jenkins-ci.plugins</groupId>-->
<!--<artifactId>node-iterator-api</artifactId>-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ public void taskCompleted(Executor executor, Queue.Task task, long durationMS) {
if( executable instanceof Run) {
Run build = (Run) executable;

getNode().setRun(build);

if( getNode().dockerTemplate.tagOnCompletion ) {
getNode().commitOnTerminate( build );
getNode().commitOnTerminate();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,24 @@ public DockerComputerLauncher(DockerTemplate template, ContainerInspectResponse

@Override
public void launch(SlaveComputer _computer, TaskListener listener) throws IOException, InterruptedException {
SSHLauncher launcher = getSSHLauncher();
launcher.launch(_computer, listener);
if( launcher.getConnection() == null ) {
LOGGER.log(Level.WARNING, "Couldn't launch Docker template. Closing.");
DockerComputer dc = (DockerComputer)_computer;
dc.getNode().terminate();

for(int tries=0;tries < 3; tries++) {
SSHLauncher launcher = getSSHLauncher();
launcher.launch(_computer, listener);

if( launcher.getConnection() != null ) {
LOGGER.log(Level.INFO, "Launched " + _computer);
return;
}

Thread.sleep(5000 * (tries+1));
}
LOGGER.log(Level.INFO, "Launched " + _computer);

LOGGER.log(Level.WARNING, "Couldn't launch Docker template. Closing.");
DockerComputer dc = (DockerComputer)_computer;
dc.getNode().terminate();


}

public SSHLauncher getSSHLauncher() throws MalformedURLException {
Expand Down
42 changes: 38 additions & 4 deletions src/main/java/com/nirima/jenkins/plugins/docker/DockerSlave.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.nirima.jenkins.plugins.docker;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.kpelykh.docker.client.DockerClient;
import com.kpelykh.docker.client.DockerException;
import com.kpelykh.docker.client.model.CommitConfig;
Expand All @@ -24,9 +25,10 @@ public class DockerSlave extends AbstractCloudSlave {
public final DockerTemplate dockerTemplate;
public final String containerId;


private transient Run theRun;

private transient boolean commitOnTermate;

public DockerSlave(DockerTemplate dockerTemplate, String containerId, String name, String nodeDescription, String remoteFS, int numExecutors, Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy, List<? extends NodeProperty<?>> nodeProperties) throws Descriptor.FormException, IOException {
super(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, nodeProperties);
this.dockerTemplate = dockerTemplate;
Expand All @@ -42,8 +44,12 @@ public String getDisplayName() {
return name;
}

public void commitOnTerminate(Run run) {
this.theRun = run;
public void setRun(Run run) {
this.theRun = run;
}

public void commitOnTerminate() {
commitOnTermate = true;
}

@Override
Expand All @@ -61,7 +67,10 @@ protected void _terminate(TaskListener listener) throws IOException, Interrupted

if( theRun != null ) {
try {
commit();
if( commitOnTermate )
commit();
else
tag(null);
} catch (DockerException e) {
LOGGER.log(Level.SEVERE, "Failure to commit instance " + containerId);
}
Expand All @@ -84,6 +93,31 @@ public void commit() throws DockerException, IOException {

String tag_image = client.commit(commitConfig);

tag(tag_image);

// SHould we add additional tags?
try
{
if( !Strings.isNullOrEmpty(dockerTemplate.additionalTag) ) {
client.tag(tag_image,dockerTemplate.additionalTag, false );
}
}
catch(DockerException ex) {
LOGGER.log(Level.SEVERE, "Could not add additional tags");
}

if( dockerTemplate.push ) {
try {
client.push(tag_image, null);
}
catch(DockerException ex) {
LOGGER.log(Level.SEVERE, "Could not push image");
}
}

}

private void tag(String tag_image) throws IOException {
theRun.addAction( new DockerBuildAction(getCloud().serverUrl, containerId, tag_image) );
theRun.save();
}
Expand Down
39 changes: 27 additions & 12 deletions src/main/java/com/nirima/jenkins/plugins/docker/DockerTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,16 @@ public class DockerTemplate implements Describable<DockerTemplate> {
private transient /*almost final*/ Set<LabelAtom> labelSet;
public transient DockerCloud parent;

public final String additionalTag;
public final boolean push;

@DataBoundConstructor
public DockerTemplate(String image, String labelString,
String remoteFs,
String credentialsId, String jvmOptions, String javaPath,
String prefixStartSlaveCmd, String suffixStartSlaveCmd,
boolean tagOnCompletion, String instanceCapStr, String dnsString
boolean tagOnCompletion, String instanceCapStr, String dnsString,
String additionalTag, boolean push
) {
this.image = image;
this.labelString = Util.fixNull(labelString);
Expand All @@ -105,6 +109,8 @@ public DockerTemplate(String image, String labelString,
}

this.dnsHosts = dnsString.split(" ");
this.additionalTag = additionalTag;
this.push = push;

readResolve();
}
Expand Down Expand Up @@ -147,7 +153,6 @@ public DockerCloud getParent() {

public DockerSlave provision(StreamTaskListener listener) throws IOException, Descriptor.FormException, DockerException {
PrintStream logger = listener.getLogger();
DockerClient dockerClient = getParent().connect();


logger.println("Launching " + image );
Expand All @@ -163,6 +168,25 @@ public DockerSlave provision(StreamTaskListener listener) throws IOException, De

List<? extends NodeProperty<?>> nodeProperties = new ArrayList();


//ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(containerId);

ContainerInspectResponse containerInspectResponse = provisionNew();
String containerId = containerInspectResponse.getId();

ComputerLauncher launcher = new DockerComputerLauncher(this, containerInspectResponse);

return new DockerSlave(this, containerId,
containerId.substring(12),
nodeDescription,
remoteFs, numExecutors, mode, labelString,
launcher, retentionStrategy, nodeProperties);

}

public ContainerInspectResponse provisionNew() throws DockerException {
DockerClient dockerClient = getParent().connect();

ContainerConfig containerConfig = new ContainerConfig();
containerConfig.setImage(image);
containerConfig.setCmd(new String[]{"/usr/sbin/sshd", "-D"});
Expand Down Expand Up @@ -191,16 +215,7 @@ public DockerSlave provision(StreamTaskListener listener) throws IOException, De

String containerId = container.getId();

ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(containerId);


ComputerLauncher launcher = new DockerComputerLauncher(this, containerInspectResponse);

return new DockerSlave(this, containerId,
containerId.substring(12),
nodeDescription,
remoteFs, numExecutors, mode, labelString,
launcher, retentionStrategy, nodeProperties);
return dockerClient.inspectContainer(containerId);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
import hudson.model.Describable;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.export.ExportedBean;

import java.io.Serializable;

/**
* Created by magnayn on 10/01/2014.
*/
@ExportedBean
public class DockerBuildAction implements Action, Serializable, Cloneable, Describable<DockerBuildAction> {

public final String containerHost;
Expand All @@ -37,8 +39,8 @@ public String getUrlName() {
return "docker";
}

public Descriptor<DockerBuildAction> getDescriptor() {
return Jenkins.getInstance().getDescriptorOrDie(getClass());
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) Jenkins.getInstance().getDescriptorOrDie(getClass());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.nirima.jenkins.plugins.docker.action;

import com.kpelykh.docker.client.DockerClient;
import hudson.model.Action;
import hudson.model.Describable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
* Action to record launching of a slave.
*/
public class DockerLaunchAction implements Action, Serializable, Cloneable{

public static class Item {
public final DockerClient client;
public final String id;

public Item(DockerClient client, String id) {
this.client = client;
this.id = id;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Item item = (Item) o;

if (!client.equals(item.client)) return false;
if (!id.equals(item.id)) return false;

return true;
}

@Override
public int hashCode() {
int result = client.hashCode();
result = 31 * result + id.hashCode();
return result;
}
}

private transient List<Item> running = new ArrayList<Item>();

public String getIconFileName() {
return null;
}

public String getDisplayName() {
return null;
}

public String getUrlName() {
return null;
}

public void started(DockerClient client, String containerName) {
running.add( new Item(client, containerName) );
}

public void stopped(DockerClient client, String containerName) {
running.remove( new Item(client, containerName) );
}

public Iterable<Item> getRunning() {
return running;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.nirima.jenkins.plugins.docker.builder;

import com.google.common.base.Strings;
import com.kpelykh.docker.client.DockerClient;
import com.kpelykh.docker.client.DockerException;
import com.nirima.jenkins.plugins.docker.DockerCloud;
import com.nirima.jenkins.plugins.docker.DockerComputer;
import com.nirima.jenkins.plugins.docker.DockerSlave;
import com.nirima.jenkins.plugins.docker.action.DockerLaunchAction;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.*;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.DataBoundConstructor;

import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;

/**
* Created by magnayn on 29/01/2014.
*/
public class DockerBuilderControl extends Builder implements Serializable {
private static final Logger LOGGER = Logger.getLogger(DockerBuilderControl.class.getName());

public final DockerBuilderControlOption option;

@DataBoundConstructor
public DockerBuilderControl(DockerBuilderControlOption option) {
this.option = option;
}

@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) super.getDescriptor();
}

@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Builder> {

@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}

@Override
public String getDisplayName() {
return "Start/Stop Docker Containers";
}

public static DescriptorExtensionList<DockerBuilderControlOption,DockerBuilderControlOptionDescriptor> getOptionList() {
return Jenkins.getInstance()
.<DockerBuilderControlOption,DockerBuilderControlOptionDescriptor>getDescriptorList(DockerBuilderControlOption.class);
}

}


@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {

try {
option.execute(build);
} catch (DockerException e) {
throw new RuntimeException(e);
}

// Save the actions
build.save();
return true;
}
}
Loading

0 comments on commit 87d670e

Please sign in to comment.