From 4394a313c7a231d797665253ff24931dcf78b6aa Mon Sep 17 00:00:00 2001 From: kpelykh Date: Fri, 19 Jul 2013 13:30:51 -0700 Subject: [PATCH] Issue #2: Switched to Java 7. Dockerfile is now using PosixFilePermission API to read file metadata and set correct file mode in tar header --- README.md | 8 +- .../kpelykh/docker/client/DockerClient.java | 1 - .../client/utils/CompressArchiveUtil.java | 16 ++ .../docker/client/utils/Permission.java | 144 ++++++++++++++++++ src/test/resources/testAddFile/Dockerfile | 2 +- src/test/resources/testAddFolder/Dockerfile | 2 +- 6 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/utils/Permission.java diff --git a/README.md b/README.md index 48020066..77c71590 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,17 @@ Java API client for [Docker](http://docs.docker.io/ "Docker") Supports Docker Client API v1.3, Server version 0.5.0 +Java-7 branch is using new Java 7 API for file manipulations to keep metadata while building Dockerbuild file. +With new API, there's *NO NEED* to explicitly set executable bit, e.g. + +run cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh + + ## Build with Maven ###### Prerequisites: -* Java 1.6+ +* Java 1.7+ * Maven 3.0.5 * Docker daemon running diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index deae28b1..79c8839b 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -28,7 +28,6 @@ import javax.ws.rs.core.MultivaluedMap; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.util.List; import java.util.UUID; diff --git a/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java b/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java index 8fdbfd3e..3e7c6973 100644 --- a/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java +++ b/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java @@ -5,18 +5,27 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; import java.util.Collection; +import java.util.Set; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.RegexFileFilter; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static org.apache.commons.io.filefilter.FileFilterUtils.*; public class CompressArchiveUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(CompressArchiveUtil.class); + public static File archiveTARFiles(File baseDir, String archiveNameWithOutExtension) throws IOException { File tarFile = null; @@ -38,6 +47,13 @@ public static File archiveTARFiles(File baseDir, String archiveNameWithOutExtens for (File file : files) { TarArchiveEntry tarEntry = new TarArchiveEntry(file); tarEntry.setName(StringUtils.substringAfter(file.toString(), baseDir.getPath())); + Set filePerm = null; + try { + filePerm = Files.getPosixFilePermissions(Paths.get(file.toURI())); + tarEntry.setMode(new Permission('-' + PosixFilePermissions.toString(filePerm)).getOctalCode()); + } catch (IOException e) { + LOGGER.trace("Could't read Posix file permissions for " + file.getPath()); + } tos.putArchiveEntry(tarEntry); diff --git a/src/main/java/com/kpelykh/docker/client/utils/Permission.java b/src/main/java/com/kpelykh/docker/client/utils/Permission.java new file mode 100644 index 00000000..f1094ec1 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/utils/Permission.java @@ -0,0 +1,144 @@ +package com.kpelykh.docker.client.utils; + +import java.util.Arrays; + + +/** + * Encapsulating unix file permissions. + * + * @version $Id$ + */ +public class Permission { + + private String mask; + + // {read, write, execute} + private boolean[] owner = new boolean[3]; + private boolean[] group = new boolean[3]; + private boolean[] other = new boolean[3]; + + /** + * @param mask the access string to parse the permissions from. + * Must be someting like -rwxrwxrwx + */ + public Permission(String mask) { + this.mask = mask; + this.owner = this.getOwnerPermissions(mask); + this.group = this.getGroupPermissions(mask); + this.other = this.getOtherPermissions(mask); +// log.debug("Permission:"+this.toString()); + } + + /** + * @return The unix access permissions including the the first bit + */ + public String getMask() { + return this.mask; + } + + /** + * @return a thee-dimensional boolean array representing read, write + * and execute permissions (in that order) of the file owner. + */ + public boolean[] getOwnerPermissions() { + return owner; + } + + /** + * @return a thee-dimensional boolean array representing read, write + * and execute permissions (in that order) of the group + */ + public boolean[] getGroupPermissions() { + return group; + } + + /** + * @return a thee-dimensional boolean array representing read, write + * and execute permissions (in that order) of any user + */ + public boolean[] getOtherPermissions() { + return other; + } + + private boolean[] getOwnerPermissions(String s) { + boolean[] b = { + s.charAt(1) == 'r', + s.charAt(2) == 'w', + s.charAt(3) == 'x' || s.charAt(3) == 's' || s.charAt(3) == 'S' || s.charAt(3) == 't' || s.charAt(3) == 'T' || s.charAt(3) == 'L'}; + return b; + } + + private boolean[] getGroupPermissions(String s) { + boolean[] b = { + s.charAt(4) == 'r', + s.charAt(5) == 'w', + s.charAt(6) == 'x' || s.charAt(6) == 's' || s.charAt(6) == 'S' || s.charAt(6) == 't' || s.charAt(6) == 'T' || s.charAt(6) == 'L'}; + return b; + } + + private boolean[] getOtherPermissions(String s) { + boolean[] b = { + s.charAt(7) == 'r', + s.charAt(8) == 'w', + s.charAt(9) == 'x' || s.charAt(9) == 's' || s.charAt(9) == 'S' || s.charAt(9) == 't' || s.charAt(9) == 'T' || s.charAt(9) == 'L'}; + return b; + } + + /** + * @return i.e. rwxrwxrwx (777) + */ + public String toString() { + return this.getMask() + " (" + this.getOctalCode() + ")"; + } + + /** + * @return The unix equivalent octal access code like 777 + */ + public int getOctalCode() { + String owner = "" + this.getOctalAccessNumber(this.getOwnerPermissions()); + String group = "" + this.getOctalAccessNumber(this.getGroupPermissions()); + String other = "" + this.getOctalAccessNumber(this.getOtherPermissions()); + return Integer.parseInt(owner + group + other); + } + + /* + * 0 = no permissions whatsoever; this person cannot read, write, or execute the file + * 1 = execute only + * 2 = write only + * 3 = write and execute (1+2) + * 4 = read only + * 5 = read and execute (4+1) + * 6 = read and write (4+2) + * 7 = read and write and execute (4+2+1) + */ + + //-rwxrwxrwx + + private int getOctalAccessNumber(boolean[] permissions) { + if (Arrays.equals(permissions, new boolean[]{false, false, false})) { + return 0; + } + if (Arrays.equals(permissions, new boolean[]{false, false, true})) { + return 1; + } + if (Arrays.equals(permissions, new boolean[]{false, true, false})) { + return 2; + } + if (Arrays.equals(permissions, new boolean[]{false, true, true})) { + return 3; + } + if (Arrays.equals(permissions, new boolean[]{true, false, false})) { + return 4; + } + if (Arrays.equals(permissions, new boolean[]{true, false, true})) { + return 5; + } + if (Arrays.equals(permissions, new boolean[]{true, true, false})) { + return 6; + } + if (Arrays.equals(permissions, new boolean[]{true, true, true})) { + return 7; + } + return -1; + } +} \ No newline at end of file diff --git a/src/test/resources/testAddFile/Dockerfile b/src/test/resources/testAddFile/Dockerfile index 6efbf091..fc576992 100644 --- a/src/test/resources/testAddFile/Dockerfile +++ b/src/test/resources/testAddFile/Dockerfile @@ -4,6 +4,6 @@ FROM ubuntu add ./testrun.sh /tmp/ -run cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh +run cp /tmp/testrun.sh /usr/local/bin/ CMD ["testrun.sh"] diff --git a/src/test/resources/testAddFolder/Dockerfile b/src/test/resources/testAddFolder/Dockerfile index 73173ad4..6f6d2c57 100644 --- a/src/test/resources/testAddFolder/Dockerfile +++ b/src/test/resources/testAddFolder/Dockerfile @@ -6,6 +6,6 @@ add . /src/ run ls -la /src -run cp /src/folderA/testAddFolder.sh /usr/local/bin/ && chmod +x /usr/local/bin/testAddFolder.sh +run cp /src/folderA/testAddFolder.sh /usr/local/bin/ CMD ["testAddFolder.sh"]