Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-46362

Stash/unstash within a Alpine container doesn't keep file attributes

      Stash and unstash of files within a container generate with kubernetes plugins doesn't keep the files attributes

      It is working fine elsewhere (slave not provided with kubernetes) but if we stash file generate within a pod or container, we get the bug

      This was working properly with version Kubernetes-plugin 0.10

      Here is a simple example of the problem, using the same pod/container.

      podTemplate(label: 'example') {
        node("example"){
          stage('checkout'){
            container("jnlp"){
              deleteDir()
              sh "touch A"
              sh "chmod a+x A"
              sh "ls -la"
      // File has the executable attribute
              stash name: 'artefact', includes: "A"
              deleteDir()
              unstash 'artefact'
              sh "ls -la" 
      // File have lost the executable attribute
            }
          }
        }
      }
      

       

      This example is pretty simple. But we use stash and unstash between pod and container quite a lot to avoid «checkout scm» + configure the code at each step.   

       

          [JENKINS-46362] Stash/unstash within a Alpine container doesn't keep file attributes

          Same problem here.

          My setup uses a Maven Wapper (mvnw) and stash/unstash was working fine until 2.60.3 (lts), but after upgrade to 2.73.1 (lts) it stopped working.

          I cannot bissect the version that introduced this regression.

          Bruno Meneguello added a comment - Same problem here. My setup uses a Maven Wapper (mvnw) and stash/unstash was working fine until 2.60.3 (lts), but after upgrade to 2.73.1 (lts) it stopped working. I cannot bissect the version that introduced this regression.

          Christophe Muller added a comment - - edited

          A question to pascallap and bkmeneguello: are you using alpine-based containers?

          Because I noticed that I only reproduced the issue when the stash operation is made in a master or slave that is based on alpine.

          Then it does not matter where the unstash is done because the executable attribute has not been "saved" by the stash operation anyway.. It looks like the implementation of chmod (https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/FilePath.java#L1639) might be different in Ubuntu (for example) and alpine.. A little groovy console script asking for whether /bin/ls is executable or not gives a faulty result in an alpine-based master for example..

          Cheers,
          Christophe.

          Christophe Muller added a comment - - edited A question to pascallap and bkmeneguello : are you using alpine-based containers? Because I noticed that I only reproduced the issue when the stash operation is made in a master or slave that is based on alpine. Then it does not matter where the unstash is done because the executable attribute has not been "saved" by the stash operation anyway.. It looks like the implementation of chmod ( https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/FilePath.java#L1639) might be different in Ubuntu (for example) and alpine.. A little groovy console script asking for whether /bin/ls is executable or not gives a faulty result in an alpine-based master for example.. Cheers, Christophe.

          In our case, yes, we are using an alpine based image.

          The provided example is using the default jnlp image from the plugin (kubernetes plugin). And this image is also based on alpine (https://github.com/jenkinsci/kubernetes-plugin/blob/25d7d2ce4aaac20245134eca2d0b711046c71e56/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java#L90)  .

           

          Thanks for the explanation, we will figure out something to fix this.

           

          Pascal Laporte added a comment - In our case, yes, we are using an alpine based image. The provided example is using the default jnlp image from the plugin (kubernetes plugin). And this image is also based on alpine ( https://github.com/jenkinsci/kubernetes-plugin/blob/25d7d2ce4aaac20245134eca2d0b711046c71e56/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java#L90 )  .   Thanks for the explanation, we will figure out something to fix this.  

          Yes, same here. Master and slaves are alpine.

          Bruno Meneguello added a comment - Yes, same here. Master and slaves are alpine.

          so I'm not sure why this would be a regression from 0.10 when alpine jnlp container was added in 0.9 in https://github.com/jenkinsci/kubernetes-plugin/commit/8857b47a4144408039510550475b8118d307036b

          but seems there is a workaround and core should be patched to work in alpine

          Carlos Sanchez added a comment - so I'm not sure why this would be a regression from 0.10 when alpine jnlp container was added in 0.9 in https://github.com/jenkinsci/kubernetes-plugin/commit/8857b47a4144408039510550475b8118d307036b but seems there is a workaround and core should be patched to work in alpine

          I have just rerun the same example using alpine 3.7 has the base image for our jnlp slave (we were using 3.6).

          Stash/Unstash is now working properly... Thanks a lot!

          Pascal Laporte added a comment - I have just rerun the same example using alpine 3.7 has the base image for our jnlp slave (we were using 3.6). Stash/Unstash is now working properly... Thanks a lot!

          Actually we still have the bug under alpine 3.7. From what I understand, when jenkins is requesting the value of a file's attributes, depending on both the core version and the OS, it sometimes receives wrong values, so in the tar file the attributes are already lost after the stash operation.

          In order to highlight that, one can simply launch a master using alpine (e.g., with docker) and run in the script console the following code:
           

          import hudson.util.*;
          import hudson.Functions;
          import hudson.Util;
          import hudson.os.PosixAPI;
          import hudson.os.PosixException;
          import java.nio.file.Files;
          import java.nio.file.InvalidPathException;
          import org.apache.commons.io.LineIterator;
          import java.io.*;
          import java.util.Collection;
          import java.util.List;
          import java.util.regex.Pattern;
          import static hudson.Util.fileToPath;
          
          println "cat /etc/issue".execute().text
          println IOUtils.mode(new File("/etc/passwd"))
          println IOUtils.mode(new File("/bin/busybox"))
          println PosixAPI.jnr().stat(new File("/etc/passwd").getPath()).mode();
          println PosixAPI.jnr().stat(new File("/bin/busybox").getPath()).mode();
          

          When using an Ubuntu-based master, the two numbers are different for /etc/passwd and /bin/busybox. But under alpine, we get the same number whereas busybox has its +x bit set. We get:

          Welcome to Alpine Linux 3.7
          Kernel \r on an \m (\l)
          
          33060
          33060
          33060
          33060
          

          Christophe Muller added a comment - Actually we still have the bug under alpine 3.7. From what I understand, when jenkins is requesting the value of a file's attributes, depending on both the core version and the OS, it sometimes receives wrong values, so in the tar file the attributes are already lost after the stash operation. In order to highlight that, one can simply launch a master using alpine (e.g., with docker) and run in the script console the following code:   import hudson.util.*; import hudson.Functions; import hudson.Util; import hudson.os.PosixAPI; import hudson.os.PosixException; import java.nio.file.Files; import java.nio.file.InvalidPathException; import org.apache.commons.io.LineIterator; import java.io.*; import java.util.Collection; import java.util.List; import java.util.regex.Pattern; import static hudson.Util.fileToPath; println "cat /etc/issue" .execute().text println IOUtils.mode( new File( "/etc/passwd" )) println IOUtils.mode( new File( "/bin/busybox" )) println PosixAPI.jnr().stat( new File( "/etc/passwd" ).getPath()).mode(); println PosixAPI.jnr().stat( new File( "/bin/busybox" ).getPath()).mode(); When using an Ubuntu-based master, the two numbers are different for /etc/passwd and /bin/busybox. But under alpine, we get the same number whereas busybox has its +x bit set. We get: Welcome to Alpine Linux 3.7 Kernel \r on an \m (\l) 33060 33060 33060 33060

            Unassigned Unassigned
            pascallap Pascal Laporte
            Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: