Search code examples
jenkinsjenkins-pipeline

Jenkins Declarative Pipeline, run groovy script on slave agent


I have a Jenkins declarative pipeline I have been running on the Jenkins master and it works fine. However, now that I have moved to trying to execute this on a slave node, the groovy scripts which are called in the pipeline can not access the files in the workspace.

My jenkinsfile looks like this...

pipeline {

agent {
  label {
        label "windows"
        customWorkspace "WS-${env.BRANCH_NAME}"
  }
}

stages {
  stage('InitialSetup') {
   steps {
     "${env.WORKSPACE}/JenkinsScripts/myScript.groovy"
    }
  }
}

I can see on the slave that it is creating the workspace, doing the checkout from git, and executing the script correctly. However, if something in the script try's to interact with the files in the workspace it fails.

If I have something simple like this...

def updateFile(String filename) {
  echo env.NODE_NAME
  filename = "${env.WORKSPACE}/path/to/file"
  def myFile = new File(filename)
  <do other things with the file>
}

...it says it can not find the file specified. It gives me the path it is looking for and I can confirm the file exists, and that the code runs when just building on the master.

Why can the script not find the files this way when in can just running on the master node? I added the "echo env.NODE_NAME" command into my groovy file and it says the script is executing on the correct node.

Thanks.


Solution

  • Turns out Groovy File commands are considered insecure, and although they will run on the master, they will not run on the slave. If you call them from a script that has the agent set to another node, it will still execute the command just fine, just on the master node, not the agent. Here's an excerpt of an article post https://support.cloudbees.com/hc/en-us/articles/230922508-Pipeline-Files-manipulation


    The operation with File class are run on master, so only works if build is run on master, in this example I create a file and check if I can access it on a node with method exists, it does not exist because the new File(file) is executed on master, to check this I search for folder Users that exist on my master but not in the node.

    stage 'file move wrong way'
    
      //it only works on master
      node('slave') {
    
        def ws = pwd()
        def context  = ws + "/testArtifact"
        def file = ws + '/file'
        sh 'touch ' + file
        sh 'ls ' + ws
    
        echo 'File on node : ' + new File(file).exists()
        echo 'Users : ' + new File('/Users').exists()
    
        sh 'mv ' + file + ' ' + context
        sh 'ls ' + ws
      }
    

    To execute file manipulation command we recommend to use native commands.

    This is a simple example of operations in shell

    stage 'Create file'
      sh 'touch test.txt'
    
    stage 'download file'
      def out='$(pwd)/download/maven.tgz'
      sh 'mkdir -p ./download'
      sh 'curl -L http://ftp.cixug.es/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz -o ' + out
    
    stage 'move/rename'
      def newName = 'mvn.tgz'
      sh 'mkdir -p $(pwd)/other'
      sh 'mv ' + out + ' ' + newName
      sh 'cp ' + newName + ' ' + out
    }