Skip to content

Commit 52d6691

Browse files
JoeryHJoery van den Hoff
andauthored
[FLINK-37183][clients] Fix symbolic links not being followed in "usrlib"
Co-authored-by: Joery van den Hoff <[email protected]>
1 parent 836fd99 commit 52d6691

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

flink-clients/src/main/java/org/apache/flink/client/program/DefaultPackagedProgramRetriever.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.io.IOException;
3636
import java.net.MalformedURLException;
3737
import java.net.URL;
38+
import java.nio.file.FileVisitOption;
3839
import java.nio.file.Files;
3940
import java.nio.file.Path;
4041
import java.util.ArrayList;
@@ -237,7 +238,7 @@ private static List<URL> getClasspathsFromUserLibDir(
237238
return Collections.emptyList();
238239
}
239240

240-
try (Stream<Path> files = Files.walk(userLibDir.toPath())) {
241+
try (Stream<Path> files = Files.walk(userLibDir.toPath(), FileVisitOption.FOLLOW_LINKS)) {
241242
return getClasspathsFromArtifacts(files, jarFile);
242243
}
243244
}

flink-clients/src/test/java/org/apache/flink/client/program/DefaultPackagedProgramRetrieverITCase.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ class DefaultPackagedProgramRetrieverITCase {
6363
ClasspathProviderExtension singleEntryClassClasspathProvider =
6464
ClasspathProviderExtension.createWithSingleEntryClass();
6565

66+
@RegisterExtension
67+
ClasspathProviderExtension symlinkClasspathProvider =
68+
ClasspathProviderExtension.createWithSymlink();
69+
6670
@RegisterExtension
6771
ClasspathProviderExtension multipleEntryClassesClasspathProvider =
6872
ClasspathProviderExtension.createWithMultipleEntryClasses();
@@ -522,6 +526,34 @@ void testRetrieveFromJarFileWithNonRootUserLib()
522526
assertThat(actualClasspath).isEqualTo(expectedClasspath);
523527
}
524528

529+
@Test
530+
void testRetrieveFromJarFileWithSymlinkUserLib()
531+
throws IOException, FlinkException, ProgramInvocationException {
532+
final File actualUsrLib = new File(symlinkClasspathProvider.getDirectory(), "usrlib");
533+
final PackagedProgramRetriever retrieverUnderTest =
534+
DefaultPackagedProgramRetriever.create(
535+
actualUsrLib,
536+
// the testJob jar is not on the user classpath
537+
testJobEntryClassClasspathProvider.getJobJar(),
538+
null,
539+
null,
540+
ClasspathProviderExtension.parametersForTestJob("suffix"),
541+
new Configuration());
542+
final JobGraph jobGraph = retrieveJobGraph(retrieverUnderTest, new Configuration());
543+
544+
assertThat(jobGraph.getUserJars())
545+
.contains(
546+
new org.apache.flink.core.fs.Path(
547+
testJobEntryClassClasspathProvider.getJobJar().toURI()));
548+
final List<String> actualClasspath =
549+
jobGraph.getClasspaths().stream().map(URL::toString).collect(Collectors.toList());
550+
final List<String> expectedClasspath =
551+
extractRelativizedURLsForJarsFromDirectory(actualUsrLib);
552+
553+
assertThat(actualClasspath).hasSize(2);
554+
assertThat(actualClasspath).isEqualTo(expectedClasspath);
555+
}
556+
525557
@Test
526558
void testRetrieveFromJarFileWithArtifacts()
527559
throws IOException, FlinkException, ProgramInvocationException {
@@ -684,6 +716,11 @@ private static List<String> extractRelativizedURLsForJarsFromDirectory(File dire
684716
final List<String> relativizedURLs = new ArrayList<>();
685717
final Path workingDirectory = FileUtils.getCurrentWorkingDirectory();
686718
for (File file : Preconditions.checkNotNull(directory.listFiles())) {
719+
if (file.isDirectory()) {
720+
relativizedURLs.addAll(extractRelativizedURLsForJarsFromDirectory(file));
721+
continue;
722+
}
723+
687724
if (!FileUtils.isJarFile(file.toPath())) {
688725
// any non-JARs are filtered by PackagedProgramRetrieverImpl
689726
continue;

flink-clients/src/test/java/org/apache/flink/client/testjar/ClasspathProviderExtension.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import java.util.stream.Collectors;
4444
import java.util.stream.StreamSupport;
4545

46+
import static org.assertj.core.api.Assertions.assertThat;
47+
4648
/**
4749
* {@code ClasspathProviderExtension} offers utility methods for creating a classpath based on
4850
* actual jars.
@@ -92,6 +94,24 @@ public static ClasspathProviderExtension createWithSingleEntryClass() {
9294
JOB_JAR_PATH.toFile());
9395
}
9496

97+
public static ClasspathProviderExtension createWithSymlink() {
98+
return new ClasspathProviderExtension(
99+
"_user_dir_with_symlink",
100+
directory -> {
101+
final File actualUsrLib = new File(directory, "usrlib");
102+
final File symLinkDir = new File(directory, "symlink");
103+
assertThat(actualUsrLib.mkdirs()).isTrue();
104+
assertThat(symLinkDir.mkdirs()).isTrue();
105+
106+
copyJar(JOB_LIB_JAR_PATH, symLinkDir);
107+
copyJar(JOB_JAR_PATH, actualUsrLib);
108+
109+
Files.createSymbolicLink(
110+
actualUsrLib.toPath().resolve("symlink"), symLinkDir.toPath());
111+
},
112+
JOB_JAR_PATH.toFile());
113+
}
114+
95115
public static ClasspathProviderExtension createWithMultipleEntryClasses() {
96116
return new ClasspathProviderExtension(
97117
"_user_dir_with_multiple_entry_classes",

0 commit comments

Comments
 (0)