| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,6 +16,7 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd<Void> { | |||
| 16 | 16 | ||
| 17 | 17 | boolean isDirChildrenOnly(); | |
| 18 | 18 | ||
| 19 | + boolean isCopyUIDGID(); | ||
| 19 | 20 | /** | |
| 20 | 21 | * Set container's id | |
| 21 | 22 | * | |
@@ -49,6 +50,14 @@ public interface CopyArchiveToContainerCmd extends SyncDockerCmd<Void> { | |||
| 49 | 50 | */ | |
| 50 | 51 | CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir); | |
| 51 | 52 | ||
| 53 | + /** | ||
| 54 | + * If set to true then ownership is set to the user and primary group at the destination | ||
| 55 | + * | ||
| 56 | + * @param copyUIDGID | ||
| 57 | + * flag to know if ownership should be set to the user and primary group at the destination | ||
| 58 | + */ | ||
| 59 | + CopyArchiveToContainerCmd withCopyUIDGID(boolean copyUIDGID); | ||
| 60 | + | ||
| 52 | 61 | /** | |
| 53 | 62 | * If this flag is set to true, all children of the local directory will be copied to the remote without the root directory. For ex: if | |
| 54 | 63 | * I have root/titi and root/tata and the remote path is /var/data. dirChildrenOnly = true will create /var/data/titi and /var/data/tata | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,6 +31,8 @@ public class CopyArchiveToContainerCmdImpl extends AbstrDockerCmd<CopyArchiveToC | |||
| 31 | 31 | ||
| 32 | 32 | private boolean dirChildrenOnly = false; | |
| 33 | 33 | ||
| 34 | + private boolean copyUIDGID = false; | ||
| 35 | + | ||
| 34 | 36 | public CopyArchiveToContainerCmdImpl(CopyArchiveToContainerCmd.Exec exec, String containerId) { | |
| 35 | 37 | super(exec); | |
| 36 | 38 | withContainerId(containerId); | |
@@ -56,6 +58,12 @@ public CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDir | |||
| 56 | 58 | return this; | |
| 57 | 59 | } | |
| 58 | 60 | ||
| 61 | + @Override | ||
| 62 | + public CopyArchiveToContainerCmd withCopyUIDGID(boolean copyUIDGID) { | ||
| 63 | + this.copyUIDGID = copyUIDGID; | ||
| 64 | + return this; | ||
| 65 | + } | ||
| 66 | + | ||
| 59 | 67 | @Override | |
| 60 | 68 | public CopyArchiveToContainerCmd withRemotePath(String remotePath) { | |
| 61 | 69 | checkNotNull(remotePath, "remotePath was not specified"); | |
@@ -106,10 +114,15 @@ public boolean isDirChildrenOnly() { | |||
| 106 | 114 | return this.dirChildrenOnly; | |
| 107 | 115 | } | |
| 108 | 116 | ||
| 117 | + @Override | ||
| 118 | + public boolean isCopyUIDGID() { | ||
| 119 | + return this.copyUIDGID; | ||
| 120 | + } | ||
| 121 | + | ||
| 109 | 122 | @Override | |
| 110 | 123 | public String toString() { | |
| 111 | - return new ToStringBuilder(this).append("cp ").append(hostResource).append(" ").append(containerId).append(":") | ||
| 112 | - .append(remotePath).toString(); | ||
| 124 | + return new ToStringBuilder(this).append("cp ").append(String.format("-a=%b ", isCopyUIDGID())) | ||
| 125 | + .append(hostResource).append(" ").append(containerId).append(":").append(remotePath).toString(); | ||
| 113 | 126 | } | |
| 114 | 127 | ||
| 115 | 128 | /** | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,7 +28,9 @@ protected Void execute(CopyArchiveToContainerCmd command) { | |||
| 28 | 28 | InputStream streamToUpload = command.getTarInputStream(); | |
| 29 | 29 | ||
| 30 | 30 | webResource.queryParam("path", command.getRemotePath()) | |
| 31 | - .queryParam("noOverwriteDirNonDir", command.isNoOverwriteDirNonDir()).request() | ||
| 31 | + .queryParam("noOverwriteDirNonDir", command.isNoOverwriteDirNonDir()) | ||
| 32 | + .queryParam("copyUIDGID", command.isCopyUIDGID()) | ||
| 33 | + .request() | ||
| 32 | 34 | .put(streamToUpload, MediaType.APPLICATION_X_TAR); | |
| 33 | 35 | ||
| 34 | 36 | return null; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,6 +4,7 @@ | |||
| 4 | 4 | import com.github.dockerjava.api.command.CreateContainerResponse; | |
| 5 | 5 | import com.github.dockerjava.api.exception.NotFoundException; | |
| 6 | 6 | import com.github.dockerjava.core.util.CompressArchiveUtil; | |
| 7 | + import com.github.dockerjava.utils.LogContainerTestCallback; | ||
| 7 | 8 | import org.apache.commons.io.FileUtils; | |
| 8 | 9 | import org.junit.Test; | |
| 9 | 10 | import org.slf4j.Logger; | |
@@ -14,12 +15,16 @@ | |||
| 14 | 15 | import java.nio.file.Files; | |
| 15 | 16 | import java.nio.file.Path; | |
| 16 | 17 | import java.nio.file.Paths; | |
| 18 | + import java.util.concurrent.TimeUnit; | ||
| 17 | 19 | ||
| 18 | 20 | import static org.hamcrest.MatcherAssert.assertThat; | |
| 21 | + import static org.hamcrest.Matchers.containsString; | ||
| 19 | 22 | import static org.hamcrest.Matchers.equalTo; | |
| 20 | 23 | import static org.hamcrest.Matchers.isEmptyOrNullString; | |
| 21 | 24 | import static org.hamcrest.Matchers.not; | |
| 25 | + import static org.hamcrest.Matchers.notNullValue; | ||
| 22 | 26 | import static org.junit.Assert.assertTrue; | |
| 27 | + import static org.junit.Assume.assumeThat; | ||
| 23 | 28 | ||
| 24 | 29 | public class CopyArchiveToContainerCmdIT extends CmdIT { | |
| 25 | 30 | public static final Logger LOG = LoggerFactory.getLogger(CopyArchiveToContainerCmdIT.class); | |
@@ -143,4 +148,71 @@ public void copyFileWithExecutePermission() throws Exception { | |||
| 143 | 148 | assertThat(exitCode, equalTo(0)); | |
| 144 | 149 | } | |
| 145 | 150 | ||
| 151 | + @Test | ||
| 152 | + public void copyFileWithUIDGID() throws Exception { | ||
| 153 | + Path with = Files.createFile(Files.createTempDirectory("copyFileWithUIDGID").resolve("uidgid.with")); | ||
| 154 | + Files.write(with, "with".getBytes()); | ||
| 155 | + | ||
| 156 | + Path without = Files.createFile(Files.createTempDirectory("copyFileWithUIDGID").resolve("uidgid.without")); | ||
| 157 | + Files.write(without, "without".getBytes()); | ||
| 158 | + | ||
| 159 | + String containerCmd = "while [ ! -f /home/uidgid.with ]; do true; done && stat -c %n:%u /home/uidgid.with /home/uidgid.without"; | ||
| 160 | + Long syncUserUid = 4L; // sync user in busybox uses uid=4 | ||
| 161 | + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") | ||
| 162 | + .withName("copyFileWithUIDGID") | ||
| 163 | + .withCmd("/bin/sh", "-c", containerCmd) | ||
| 164 | + .withUser(syncUserUid.toString()) | ||
| 165 | + .exec(); | ||
| 166 | + // start the container | ||
| 167 | + dockerRule.getClient().startContainerCmd(container.getId()).exec(); | ||
| 168 | + | ||
| 169 | + dockerRule.getClient().copyArchiveToContainerCmd(container.getId()) | ||
| 170 | + .withRemotePath("/home/") | ||
| 171 | + .withHostResource(without.toString()) | ||
| 172 | + .withCopyUIDGID(false) | ||
| 173 | + .exec(); | ||
| 174 | + dockerRule.getClient().copyArchiveToContainerCmd(container.getId()) | ||
| 175 | + .withRemotePath("/home/") | ||
| 176 | + .withHostResource(with.toString()) | ||
| 177 | + .withCopyUIDGID(true) | ||
| 178 | + .exec(); | ||
| 179 | + | ||
| 180 | + // await exit code | ||
| 181 | + int exitCode = dockerRule.getClient().waitContainerCmd(container.getId()) | ||
| 182 | + .start() | ||
| 183 | + .awaitStatusCode(); | ||
| 184 | + // check result | ||
| 185 | + assertThat(exitCode, equalTo(0)); | ||
| 186 | + | ||
| 187 | + LogContainerTestCallback loggingCallback = new LogContainerTestCallback(true); | ||
| 188 | + | ||
| 189 | + dockerRule.getClient().logContainerCmd(container.getId()) | ||
| 190 | + .withStdOut(true) | ||
| 191 | + .withTailAll() | ||
| 192 | + .exec(loggingCallback); | ||
| 193 | + | ||
| 194 | + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); | ||
| 195 | + String containerOutput = loggingCallback.toString(); | ||
| 196 | + | ||
| 197 | + assertThat(containerOutput, containsString(String.format("/home/uidgid.with:%d", syncUserUid))); | ||
| 198 | + | ||
| 199 | + Long hostUid = getHostUidIfPossible(); | ||
| 200 | + assumeThat("could not get the uid on host platform", hostUid, notNullValue(Long.class)); | ||
| 201 | + assertThat(containerOutput, containsString(String.format("/home/uidgid.without:%d", hostUid))); | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + private static Long getHostUidIfPossible() { | ||
| 205 | + try { | ||
| 206 | + Class<?> unixSystemClazz = Class.forName("com.sun.security.auth.module.UnixSystem"); | ||
| 207 | + Object unixSystem = unixSystemClazz.newInstance(); | ||
| 208 | + Object uid = unixSystemClazz.getMethod("getUid").invoke(unixSystem); | ||
| 209 | + if (uid == null) { | ||
| 210 | + return null; | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + return uid instanceof Long ? (Long) uid : Long.parseLong(uid.toString()); | ||
| 214 | + } catch (Exception e) { | ||
| 215 | + return null; | ||
| 216 | + } | ||
| 217 | + } | ||
| 146 | 218 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments