summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@yahooinc.com>2021-10-15 11:48:53 +0200
committerValerij Fredriksen <valerijf@yahooinc.com>2021-10-15 11:48:53 +0200
commitfa2aa2c40a3028752d861592f4a9b37982b80797 (patch)
tree520ac7d961bd50ac289718413a43c3214a4c51b4
parent7f1f9e3d1d17d176c13d183d4131f58c808c2141 (diff)
Add support for symlinks
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemProvider.java16
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemTest.java46
2 files changed, 61 insertions, 1 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemProvider.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemProvider.java
index 73cd3f8cfc5..a85e4ee8699 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemProvider.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemProvider.java
@@ -121,6 +121,20 @@ class ContainerFileSystemProvider extends FileSystemProvider {
}
@Override
+ public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException {
+ Path pathOnHost = pathOnHost(link);
+ if (target instanceof ContainerPath)
+ target = pathOnHost.getFileSystem().getPath(toContainerPath(target).pathInContainer());
+ provider(pathOnHost).createSymbolicLink(pathOnHost, target, attrs);
+ }
+
+ @Override
+ public Path readSymbolicLink(Path link) throws IOException {
+ Path pathOnHost = pathOnHost(link);
+ return provider(pathOnHost).readSymbolicLink(pathOnHost);
+ }
+
+ @Override
public boolean isSameFile(Path path, Path path2) throws IOException {
// 'path' FS provider should be 'this'
if (path2 instanceof ContainerPath)
@@ -250,7 +264,7 @@ class ContainerFileSystemProvider extends FileSystemProvider {
private static <T> T cast(Object value, Class<T> type) {
if (type.isInstance(value)) return type.cast(value);
- throw new ProviderMismatchException("Expected " + type.getName() + ", was " + value.getClass().getName());
+ throw new ProviderMismatchException("Expected " + type.getSimpleName() + ", was " + value.getClass().getName());
}
private static Path pathOnHost(Path path) {
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemTest.java
index eb15450b756..fcd8e0ec406 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerFileSystemTest.java
@@ -9,6 +9,8 @@ import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
import java.util.Map;
import static com.yahoo.vespa.hosted.node.admin.task.util.fs.ContainerUserPrincipalLookupService.OVERFLOW_ID;
@@ -52,6 +54,21 @@ class ContainerFileSystemTest {
Files.copy(hostFile.toPath(), destination);
assertOwnership(destination, 0, 0, 10000, 11000);
+
+ // Set owner + group on both source host file and destination container file
+ hostFile.setOwnerId(5).setGroupId(10);
+ new UnixPath(destination).setOwnerId(500).setGroupId(200);
+ assertOwnership(destination, 500, 200, 10500, 11200);
+ // Copy the host file to destination again with COPY_ATTRIBUTES and REPLACE_EXISTING
+ Files.copy(hostFile.toPath(), destination, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
+ // The destination is recreated, so the owner should be root
+ assertOwnership(destination, 0, 0, 10000, 11000);
+
+ // Set owner + group and copy within ContainerFS
+ new UnixPath(destination).setOwnerId(500).setGroupId(200);
+ ContainerPath destination2 = ContainerPath.fromPathInContainer(containerFs, Path.of("/dest2"));
+ Files.copy(destination, destination2, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
+ assertOwnership(destination2, 0, 0, 10000, 11000);
}
@Test
@@ -67,6 +84,35 @@ class ContainerFileSystemTest {
hostFile.createNewFile();
Files.move(hostFile.toPath(), destination);
assertOwnership(destination, 0, 0, 10000, 11000);
+
+ // Set owner + group on both source host file and destination container file
+ hostFile.createNewFile();
+ hostFile.setOwnerId(5).setGroupId(10);
+ new UnixPath(destination).setOwnerId(500).setGroupId(200);
+ assertOwnership(destination, 500, 200, 10500, 11200);
+ // Move the host file to destination again with COPY_ATTRIBUTES and REPLACE_EXISTING
+ Files.move(hostFile.toPath(), destination, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
+ // The destination is recreated, so the owner should be root
+ assertOwnership(destination, 0, 0, 10000, 11000);
+
+ // Set owner + group and move within ContainerFS
+ new UnixPath(destination).setOwnerId(500).setGroupId(200);
+ ContainerPath destination2 = ContainerPath.fromPathInContainer(containerFs, Path.of("/dest2"));
+ Files.move(destination, destination2, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
+ assertOwnership(destination2, 0, 0, 10000, 11000);
+ }
+
+ @Test
+ public void symlink() throws IOException {
+ ContainerPath source = ContainerPath.fromPathInContainer(containerFs, Path.of("/src"));
+ // Symlink from ContainerPath to some relative path (different FS provider)
+ Files.createSymbolicLink(source, fileSystem.getPath("../relative/target"));
+ assertEquals(fileSystem.getPath("../relative/target"), Files.readSymbolicLink(source));
+ Files.delete(source);
+
+ // Symlinks from ContainerPath to a ContainerPath: Target is resolved within container with base FS provider
+ Files.createSymbolicLink(source, ContainerPath.fromPathInContainer(containerFs, Path.of("/path/in/container")));
+ assertEquals(fileSystem.getPath("/path/in/container"), Files.readSymbolicLink(source));
}
private static void assertOwnership(ContainerPath path, int contUid, int contGid, int hostUid, int hostGid) throws IOException {