2

Through my own plugin, I need to know about the existence of a file in the workspace of a Jenkins slave. But the file can't be found whereas it really exists on the slave

artifactsToDeploy = workingDir.act(new FilesDeployerCallable(listener, pairs, artifactoryServer, credentials,
                repositoryKey, propertiesToAdd,
                artifactoryServer.createProxyConfiguration(Jenkins.getInstance().proxy),configurator.getProductKey(),configurator.getArtifactoryKey(), configurator.getBuildType() ,configurator.getRpmParameters(),build,configurator.issendFcmPayload(), configurator.getModule(), configurator.getTaxonomy()));
    }

private static class FilesDeployerCallable implements FilePath.FileCallable<List<Artifact>> {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private final String repositoryKey;
        private BuildListener listener;
        private Multimap<String, String> patternPairs;
        private ArtifactoryServer server;
        private Credentials credentials;
        private ArrayListMultimap<String, String> buildProperties;
        private ProxyConfiguration proxyConfiguration;
        private String artifactKey;
        private String buildType;
        private String module;
        private String taxonomy;
        private RpmParameters rpmParameters;
        private final AbstractBuild build;
        private boolean sendFcmPayload;
        private EnvVars env;

        public FilesDeployerCallable(BuildListener listener, Multimap<String, String> patternPairs,
                                     ArtifactoryServer server, Credentials credentials, String repositoryKey,
                                     ArrayListMultimap<String, String> buildProperties, ProxyConfiguration proxyConfiguration,String productKey,String artifactKey, String buildType, RpmParameters rpmParameters, AbstractBuild build, boolean sendFcmPayload, String module, String taxonomy) throws IOException, InterruptedException {
            this.listener = listener;
            this.patternPairs = patternPairs;
            this.server = server;
            this.credentials = credentials;
            this.repositoryKey = repositoryKey;
            this.buildProperties = buildProperties;
            this.proxyConfiguration = proxyConfiguration;
            this.artifactKey = artifactKey;
            this.buildType = buildType;
            this.module = module;
            this.taxonomy = taxonomy;
            this.rpmParameters = rpmParameters;
            this.build = build;
            this.sendFcmPayload = sendFcmPayload;
            this.env = build.getEnvironment(listener);

        }

java.io.IOException: remote file operation failed: /jenkins/slaveworkspace/workspace/githubMigration at hudson.remoting.Channel@44434cf3:master-replicated: java.io.IOException: Unable to serialize hudson.FilePath$FileCallableWrapper@2ca3869b at hudson.FilePath.act(FilePath.java:977) at hudson.FilePath.act(FilePath.java:959) at dj.pib.productivity.generic.GenericArtifactsDeployer.deploy(GenericArtifactsDeployer.java:148) at dj.pib.productivity.generic.ArtifactoryGenericConfigurator$1.tearDown(ArtifactoryGenericConfigurator.java:352) at hudson.model.Build$BuildExecution.doRun(Build.java:171) at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:533) at hudson.model.Run.execute(Run.java:1759) at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43) at hudson.model.ResourceController.execute(ResourceController.java:89) at hudson.model.Executor.run(Executor.java:240) Caused by: java.io.IOException: Unable to serialize hudson.FilePath$FileCallableWrapper@2ca3869b at hudson.remoting.UserRequest.serialize(UserRequest.java:169) at hudson.remoting.UserRequest.(UserRequest.java:63) at hudson.remoting.Channel.call(Channel.java:750) at hudson.FilePath.act(FilePath.java:970) ... 9 more Caused by: java.io.NotSerializableException: hudson.model.FreeStyleBuild at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347) at hudson.remoting.UserRequest._serialize(UserRequest.java:158) at hudson.remoting.UserRequest.serialize(UserRequest.java:167) ... 12 more Collecting metadata...

what am I doing wrong?

Edit 1: Okay, I see the problem is I am passing AbstractBuild build in filesDeployerCallable which is not serializable but I need it for stuff I do. It does give me a warning as to (abstract is raw type and should be parameterized). How Do I parameterize it ? its in the hudson.model.abstractModel

Scooby
  • 3,371
  • 8
  • 44
  • 84
  • How many slaves do you have and assuming your plugin operates on the master, how will it know which slave to look at for the file? P.S: your constructor args seem to be too many. Can you probably take a look at the builder pattern to create an instance? – Praba Jun 10 '15 at 01:39
  • @prabugp - please see edit1 – Scooby Jun 10 '15 at 01:53
  • Can't you run your plugin in the slaves? (check: http://stackoverflow.com/a/9281190/2231632 ) If so, you can get all the necessary information from the slave itself. And you'd need to know what type of Build it is. For example `FreeStyleBuild`, of Maven build if you have the plugin and so on. Parameterizing is not a problem but serializing it is. – Praba Jun 10 '15 at 01:59
  • @prabugp- I cant run on the slaves as this is a fork of artifactory plugin which doesn't follow the virtual channel route. Anyhow, the build type is always going to be freestyle build. So I need a way to serialize it, I figured if I was able to parameterize it, serializing should just follow ? – Scooby Jun 10 '15 at 02:11

1 Answers1

2

To answer the question How to find out if file exists on a slave, it should be enough to call workspace.child("relative/path/to/my.file").exists() from master. Hiding the difference between local and remote files is the reason FilePath exist.


There are several way to get around Jenkins model objects not being serializable.

  1. Keep the logic on master and send small tasks (Callables) on slave. It is easier to make sure those tasks are simple enough they will never need Jenkins model objects. Using hudson.Launcher and hudson.FilePath falls into this category.
  2. Extract only serializable information before sending Callable to slave. For example if all you need is a build number, there is no need to transfer whole build object.
  3. Use object proxies so only a remote proxy of a domain object will be present on a slave and all method calls will be dispatched over a channel.
Oliver Gondža
  • 3,386
  • 4
  • 29
  • 49