Skip to content

Commit

Permalink
[JENKINS-48766] - Make the RemotingVersionInfo API publicly available
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-nenashev committed Jan 22, 2018
1 parent ef2a432 commit 0ca8572
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 20 deletions.
7 changes: 7 additions & 0 deletions core/src/main/java/jenkins/MasterToSlaveFileCallable.java
@@ -1,12 +1,19 @@
package jenkins;

import hudson.FilePath.FileCallable;
import hudson.remoting.VirtualChannel;
import jenkins.security.Roles;
import jenkins.slaves.RemotingVersionInfo;
import org.jenkinsci.remoting.RoleChecker;

import java.io.File;

/**
* {@link FileCallable}s that are meant to be only used on the master.
*
* Note that the logic within {@link #invoke(File, VirtualChannel)} should use API of a minimum supported Remoting version.
* See {@link RemotingVersionInfo#getMinimumSupportedVersion()}.
*
* @since 1.587 / 1.580.1
* @param <T> the return type; note that this must either be defined in your plugin or included in the stock JEP-200 whitelist
*/
Expand Down
Expand Up @@ -3,6 +3,7 @@
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.ChannelClosedException;
import jenkins.slaves.RemotingVersionInfo;
import org.jenkinsci.remoting.RoleChecker;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
Expand All @@ -11,6 +12,9 @@
/**
* Convenient {@link Callable} meant to be run on agent.
*
* Note that the logic within {@link #call()} should use API of a minimum supported Remoting version.
* See {@link RemotingVersionInfo#getMinimumSupportedVersion()}.
*
* @author Kohsuke Kawaguchi
* @since 1.587 / 1.580.1
* @param <V> the return type; note that this must either be defined in your plugin or included in the stock JEP-200 whitelist
Expand Down
51 changes: 31 additions & 20 deletions core/src/main/java/jenkins/slaves/RemotingVersionInfo.java
Expand Up @@ -24,10 +24,7 @@
package jenkins.slaves;

import hudson.util.VersionNumber;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -39,17 +36,17 @@
/**
* Provides information about Remoting versions used within the core.
* @author Oleg Nenashev
* @since TODO
*/
@Restricted(NoExternalUse.class)
public class RemotingVersionInfo {

private static final Logger LOGGER = Logger.getLogger(RemotingVersionInfo.class.getName());
private static final String RESOURCE_NAME="remoting-info.properties";

@CheckForNull
@Nonnull
private static VersionNumber EMBEDDED_VERSION;

@CheckForNull
@Nonnull
private static VersionNumber MINIMUM_SUPPORTED_VERSION;

private RemotingVersionInfo() {}
Expand All @@ -64,39 +61,53 @@ private RemotingVersionInfo() {}
LOGGER.log(Level.WARNING, "Failed to load Remoting Info from " + RESOURCE_NAME, e);
}

EMBEDDED_VERSION = tryExtractVersion(props, "remoting.embedded.version");
MINIMUM_SUPPORTED_VERSION = tryExtractVersion(props, "remoting.minimum.supported.version");
EMBEDDED_VERSION = extractVersion(props, "remoting.embedded.version");
MINIMUM_SUPPORTED_VERSION = extractVersion(props, "remoting.minimum.supported.version");
}

@CheckForNull
private static VersionNumber tryExtractVersion(@Nonnull Properties props, @Nonnull String propertyName) {
@Nonnull
private static VersionNumber extractVersion(@Nonnull Properties props, @Nonnull String propertyName)
throws ExceptionInInitializerError {
String prop = props.getProperty(propertyName);
if (prop == null) {
LOGGER.log(Level.FINE, "Property {0} is not defined in {1}", new Object[] {propertyName, RESOURCE_NAME});
return null;
throw new ExceptionInInitializerError(String.format(
"Property %s is not defined in %s", propertyName, RESOURCE_NAME));
}

if(prop.contains("${")) { // Due to whatever reason, Maven does not nullify them
LOGGER.log(Level.WARNING, "Property {0} in {1} has unresolved variable(s). Raw value: {2}",
new Object[] {propertyName, RESOURCE_NAME, prop});
return null;
throw new ExceptionInInitializerError(String.format(
"Property %s in %s has unresolved variable(s). Raw value: %s",
propertyName, RESOURCE_NAME, prop));
}

try {
return new VersionNumber(prop);
} catch (RuntimeException ex) {
LOGGER.log(Level.WARNING, String.format("Failed to parse version for for property %s in %s. Raw Value: %s",
propertyName, RESOURCE_NAME, prop), ex);
return null;
throw new ExceptionInInitializerError(new IOException(
String.format("Failed to parse version for for property %s in %s. Raw Value: %s",
propertyName, RESOURCE_NAME, prop), ex));
}
}

@CheckForNull
/**
* Returns a version which is embedded into the Jenkins core.
* Note that this version <b>may</b> differ from one which is being really used in Jenkins.
* @return Remoting version
*/
@Nonnull
public static VersionNumber getEmbeddedVersion() {
return EMBEDDED_VERSION;
}

@CheckForNull
/**
* Gets Remoting version which is supported by the core.
* Jenkins core and plugins make invoke operations on agents (e.g. {@link jenkins.security.MasterToSlaveCallable})
* and use Remoting-internal API within them.
* In such case this API should be present on the remote side.
* This method defines a minimum expected version, so that all calls should use a compatible API.
* @return Minimal Remoting version for API calls.
*/
@Nonnull
public static VersionNumber getMinimumSupportedVersion() {
return MINIMUM_SUPPORTED_VERSION;
}
Expand Down

0 comments on commit 0ca8572

Please sign in to comment.