Skip to content

Commit

Permalink
Make variables optional (#105)
Browse files Browse the repository at this point in the history
* Make variables optional

Signed-off-by: Kanstantsin Shautsou <[email protected]>

* WIP

* wip

* only for cloud slave

* Findbugs

* Findbugs
  • Loading branch information
KostyaSha authored Nov 1, 2017
1 parent db0026e commit f4e0c04
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.github.kostyasha.yad.DockerConnector;
import com.github.kostyasha.yad.DockerConnector.DescriptorImpl;
import com.github.kostyasha.yad.DockerContainerLifecycle;
import com.github.kostyasha.yad.DockerNodeProperty;
import com.github.kostyasha.yad.DockerSlaveTemplate;
import com.github.kostyasha.yad.commons.DockerPullImage;
import com.github.kostyasha.yad.commons.DockerRemoveContainer;
Expand Down Expand Up @@ -73,6 +74,9 @@ public class FreestyleTest implements Serializable {
private static final String DOCKER_CLOUD_LABEL = "docker-label";
private static final String DOCKER_CLOUD_NAME = "docker-cloud";
private static final String TEST_VALUE = "2323re23e";
private static final String CONTAINER_ID = "CONTAINER_ID";
private static final String CLOUD_ID = "CLOUD_ID";
private static final String DOCKER_HOST = "SOME_HOST";

@Parameterized.Parameters(name = "{0}")
public static Iterable<String> data() {
Expand Down Expand Up @@ -212,8 +216,11 @@ public Boolean call() throws Throwable {
//template
final Entry entry = new Entry("super-key", TEST_VALUE);
final EnvironmentVariablesNodeProperty nodeProperty = new EnvironmentVariablesNodeProperty(entry);

final ArrayList<NodeProperty<?>> nodeProperties = new ArrayList<>();
nodeProperties.add(nodeProperty);
nodeProperties.add(new DockerNodeProperty(CONTAINER_ID, CLOUD_ID, DOCKER_HOST));


final DockerSlaveTemplate slaveTemplate = new DockerSlaveTemplate();
slaveTemplate.setMaxCapacity(4);
Expand Down Expand Up @@ -278,6 +285,7 @@ public Boolean call() throws Throwable {
assertThat(lastBuild.getResult(), is(Result.SUCCESS));

assertThat(getLog(lastBuild), Matchers.containsString(TEST_VALUE));
assertThat(getLog(lastBuild), Matchers.containsString(CLOUD_ID + "=" + DOCKER_CLOUD_NAME));

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
import java.io.IOException;
import java.net.URISyntaxException;

import static java.util.Objects.isNull;

/**
* Contribute docker related vars in build.
* TODO seems this will never satisfy all use cases and dumping inspect json into WS
* will be more generic solution
*
* @author Kanstantsin Shautsou
* @see DockerNodeProperty
*/
@Extension
public class DockerEnvironmentContributor extends EnvironmentContributor {
Expand All @@ -31,24 +33,44 @@ public void buildEnvironmentFor(@Nonnull Run run, @Nonnull EnvVars envs, @Nonnul
final Executor executor = run.getExecutor();
if (executor != null && executor.getOwner() instanceof DockerComputer) {
final DockerComputer dockerComputer = (DockerComputer) executor.getOwner();
listener.getLogger().println("[YAD-PLUGIN] Injecting DOCKER_CONTAINER_ID variable.");
envs.put("DOCKER_CONTAINER_ID", dockerComputer.getContainerId());
listener.getLogger().println("[YAD-PLUGIN] Injecting JENKINS_CLOUD_ID variable.");
envs.put("JENKINS_CLOUD_ID", dockerComputer.getCloudId());
try {
//replace http:// and https:// from docker-java to tcp://
final DockerCloud cloud = dockerComputer.getCloud(); // checkfornull
if (cloud != null && cloud.getConnector() != null) {
final URIBuilder uriBuilder = new URIBuilder(cloud.getConnector().getServerUrl());
if (!uriBuilder.getScheme().equals("unix")) {
uriBuilder.setScheme("tcp");
DockerSlave node = dockerComputer.getNode();
if (isNull(node)) {
LOG.debug("{} is missing it's node, skipping...", dockerComputer.getName());
return;
}

final DockerNodeProperty dProp = node.getNodeProperties().get(DockerNodeProperty.class);
if (dProp == null) {
return;
}

if (dProp.isContainerIdCheck()) {
listener.getLogger().println("[YAD-PLUGIN] Injecting variable: " + dProp.getContainerId());
envs.put(dProp.getContainerId(), dockerComputer.getContainerId());
}

if (dProp.isCloudIdCheck()) {
listener.getLogger().println("[YAD-PLUGIN] Injecting variable: " + dProp.getCloudId());
envs.put(dProp.getCloudId(), dockerComputer.getCloudId());
}

if (dProp.isDockerHostCheck()) {
try {
//replace http:// and https:// from docker-java to tcp://
final DockerCloud cloud = dockerComputer.getCloud(); // checkfornull
if (cloud != null && cloud.getConnector() != null) {
final URIBuilder uriBuilder = new URIBuilder(cloud.getConnector().getServerUrl());
if (!uriBuilder.getScheme().equals("unix")) {
uriBuilder.setScheme("tcp");
}

listener.getLogger().println("[YAD-PLUGIN] Injecting variable: " + dProp.getDockerHost());
envs.put(dProp.getDockerHost(), uriBuilder.toString());
}
listener.getLogger().println("[YAD-PLUGIN] DOCKER_HOST variable.");
envs.put("DOCKER_HOST", uriBuilder.toString());
} catch (URISyntaxException e) {
listener.error("Can't make variable: %s", dProp.getDockerHost(), e);
LOG.error("Can't make '{}' variable: {}", dProp.getDockerHost(), e);
}
} catch (URISyntaxException e) {
listener.error("Can't build 'DOCKER_HOST' variable: {}", e.getMessage());
LOG.error("Can't build 'DOCKER_HOST' var: {}", e.getMessage());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.github.kostyasha.yad;

import hudson.Extension;
import hudson.model.Node;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;

import javax.annotation.Nonnull;

/**
* @author Kanstantsin Shautsou
*/
public class DockerNodeProperty extends NodeProperty<Node> {

private String containerId = "DOCKER_CONTAINER_ID";
private boolean containerIdCheck = true;

private String cloudId = "JENKINS_CLOUD_ID";
private boolean cloudIdCheck = true;

private String dockerHost = "DOCKER_HOST";
private boolean dockerHostCheck = true;


// Default UI
public DockerNodeProperty() {
}

public DockerNodeProperty(String containerId, String cloudId, String dockerHost) {
this.containerId = containerId;
this.containerIdCheck = true;

this.cloudId = cloudId;
this.cloudIdCheck = true;

this.dockerHost = dockerHost;
this.dockerHostCheck = true;
}

// Crazy UI binding
@DataBoundConstructor
public DockerNodeProperty(String containerId, boolean containerIdCheck,
String cloudId, boolean cloudIdCheck,
String dockerHost, boolean dockerHostCheck) {
this.containerId = containerId;
this.containerIdCheck = containerIdCheck;

this.cloudId = cloudId;
this.cloudIdCheck = cloudIdCheck;

this.dockerHost = dockerHost;
this.dockerHostCheck = dockerHostCheck;
}

public String getContainerId() {
return containerId;
}

public String getCloudId() {
return cloudId;
}

public String getDockerHost() {
return dockerHost;
}

public boolean isContainerIdCheck() {
return containerIdCheck;
}

public boolean isCloudIdCheck() {
return cloudIdCheck;
}

public boolean isDockerHostCheck() {
return dockerHostCheck;
}

@Symbol("dockerEnvVars")
@Extension
public static class DescriptorImpl extends NodePropertyDescriptor {
@Override
public boolean isApplicable(Class<? extends Node> targetType) {
return targetType.isAssignableFrom(DockerSlave.class);
}

@Nonnull
@Override
public String getDisplayName() {
return "Docker variables";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class DockerSlaveConfig extends AbstractDescribableImpl<DockerSlaveConfig
*/
protected DockerContainerLifecycle dockerContainerLifecycle = new DockerContainerLifecycle();

private List<? extends NodeProperty<?>> nodeProperties = emptyList();
protected List<NodeProperty<?>> nodeProperties = emptyList();

public DockerSlaveConfig() {
this.id = randomUUID().toString();
Expand Down Expand Up @@ -138,11 +138,11 @@ public void setRemoteFs(String remoteFs) {
}

@Nonnull
public List<? extends NodeProperty<?>> getNodeProperties() {
public List<NodeProperty<?>> getNodeProperties() {
return nonNull(nodeProperties) ? unmodifiableList(nodeProperties) : emptyList();
}

public void setNodeProperties(List<? extends NodeProperty<?>> nodeProperties) {
public void setNodeProperties(List<NodeProperty<?>> nodeProperties) {
this.nodeProperties = nodeProperties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
Expand All @@ -32,6 +33,7 @@
*/
public class DockerSlaveTemplate extends DockerSlaveConfig {
private static final Logger LOG = LoggerFactory.getLogger(DockerSlaveTemplate.class);
private int configVersion = 1;

private int maxCapacity = 10;

Expand Down Expand Up @@ -59,7 +61,7 @@ public DockerSlaveTemplate(@Nonnull String id) throws FormException {
* FIXME DescribableList doesn't work with DBS https://gist.github.com/KostyaSha/3414f4f453ea7c7406b4
*/
@DataBoundConstructor
public DockerSlaveTemplate(@Nonnull String id, List<? extends NodeProperty<?>> nodeProperties)
public DockerSlaveTemplate(@Nonnull String id, List<NodeProperty<?>> nodeProperties)
throws FormException {
this(id);
setNodeProperties(nodeProperties);
Expand Down Expand Up @@ -123,6 +125,12 @@ public DockerComputerLauncher getLauncher() {
*/
@SuppressWarnings("unused")
public Object readResolve() {
if (configVersion < 1) {
if (isNull(nodeProperties)) nodeProperties = new ArrayList<>();
nodeProperties.add(new DockerNodeProperty("DOCKER_CONTAINER_ID", "JENKINS_CLOUD_ID", "DOCKER_HOST"));
configVersion = 1;
}

// real @Nonnull
if (mode == null) {
mode = Node.Mode.NORMAL;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.github.kostyasha.yad.DockerNodeProperty

import com.github.kostyasha.yad.DockerNodeProperty
import lib.FormTagLib

def f = namespace(FormTagLib);
def st = namespace("jelly:stapler")

if (instance == null) {
instance = new DockerNodeProperty()
}

// intend somehow
f.block() {
f.optionalBlock(
title: _("Docker Container ID"),
field: "containerIdCheck",
inline: true
) {
f.entry(title: "Variable name") {
f.textbox(field: "containerId")
}
}

f.optionalBlock(
title: _("Docker Cloud ID"),
field: "cloudIdCheck",
inline: true
) {
f.entry(title: "Variable name") {
f.textbox(field: "cloudId")
}
}

f.optionalBlock(
title: _("Docker Host URL"),
field: "dockerHostCheck",
inline: true
) {
f.entry(title: "Variable name") {
f.textbox(field: "dockerHost")
}
}
}

0 comments on commit f4e0c04

Please sign in to comment.