Merge branch '3.4.x'
This commit is contained in:
commit
fc01b011d5
|
@ -100,7 +100,7 @@ class FileWatcher implements Closeable {
|
||||||
|
|
||||||
private static Path resolveSymlinkIfNecessary(Path path) throws IOException {
|
private static Path resolveSymlinkIfNecessary(Path path) throws IOException {
|
||||||
if (Files.isSymbolicLink(path)) {
|
if (Files.isSymbolicLink(path)) {
|
||||||
Path target = Files.readSymbolicLink(path);
|
Path target = path.resolveSibling(Files.readSymbolicLink(path));
|
||||||
return resolveSymlinkIfNecessary(target);
|
return resolveSymlinkIfNecessary(target);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -31,6 +31,8 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import org.springframework.util.FileSystemUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
@ -40,6 +42,7 @@ import static org.assertj.core.api.Assertions.fail;
|
||||||
* Tests for {@link FileWatcher}.
|
* Tests for {@link FileWatcher}.
|
||||||
*
|
*
|
||||||
* @author Moritz Halbritter
|
* @author Moritz Halbritter
|
||||||
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
class FileWatcherTests {
|
class FileWatcherTests {
|
||||||
|
|
||||||
|
@ -191,6 +194,74 @@ class FileWatcherTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replicating a letsencrypt folder structure like:
|
||||||
|
* "/folder/live/certname/privkey.pem -> ../../archive/certname/privkey32.pem"
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void shouldFollowRelativePathSymlinks(@TempDir Path tempDir) throws Exception {
|
||||||
|
Path folder = tempDir.resolve("folder");
|
||||||
|
Path live = folder.resolve("live").resolve("certname");
|
||||||
|
Path archive = folder.resolve("archive").resolve("certname");
|
||||||
|
Path link = live.resolve("privkey.pem");
|
||||||
|
Path targetFile = archive.resolve("privkey32.pem");
|
||||||
|
Files.createDirectories(live);
|
||||||
|
Files.createDirectories(archive);
|
||||||
|
Files.createFile(targetFile);
|
||||||
|
Path relativePath = Path.of("../../archive/certname/privkey32.pem");
|
||||||
|
Files.createSymbolicLink(link, relativePath);
|
||||||
|
try {
|
||||||
|
WaitingCallback callback = new WaitingCallback();
|
||||||
|
this.fileWatcher.watch(Set.of(link), callback);
|
||||||
|
Files.writeString(targetFile, "Some content");
|
||||||
|
callback.expectChanges();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
FileSystemUtils.deleteRecursively(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replicating a k8s configmap folder structure like:
|
||||||
|
* "secret.txt -> ..data/secret.txt",
|
||||||
|
* "..data/ -> ..a72e81ff-f0e1-41d8-a19b-068d3d1d4e2f/",
|
||||||
|
* "..a72e81ff-f0e1-41d8-a19b-068d3d1d4e2f/secret.txt"
|
||||||
|
*
|
||||||
|
* After a secret update, this will look like: "secret.txt -> ..data/secret.txt",
|
||||||
|
* "..data/ -> ..bba2a61f-ce04-4c35-93aa-e455110d4487/",
|
||||||
|
* "..bba2a61f-ce04-4c35-93aa-e455110d4487/secret.txt"
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void shouldTriggerOnConfigMapUpdates(@TempDir Path tempDir) throws Exception {
|
||||||
|
Path configMap1 = createConfigMap(tempDir, "secret.txt");
|
||||||
|
Path configMap2 = createConfigMap(tempDir, "secret.txt");
|
||||||
|
Path data = tempDir.resolve("..data");
|
||||||
|
Files.createSymbolicLink(data, configMap1);
|
||||||
|
Path secretFile = tempDir.resolve("secret.txt");
|
||||||
|
Files.createSymbolicLink(secretFile, data.resolve("secret.txt"));
|
||||||
|
try {
|
||||||
|
WaitingCallback callback = new WaitingCallback();
|
||||||
|
this.fileWatcher.watch(Set.of(secretFile), callback);
|
||||||
|
Files.delete(data);
|
||||||
|
Files.createSymbolicLink(data, configMap2);
|
||||||
|
FileSystemUtils.deleteRecursively(configMap1);
|
||||||
|
callback.expectChanges();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
FileSystemUtils.deleteRecursively(configMap2);
|
||||||
|
Files.delete(data);
|
||||||
|
Files.delete(secretFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Path createConfigMap(Path parentDir, String secretFileName) throws IOException {
|
||||||
|
Path configMapFolder = parentDir.resolve(".." + UUID.randomUUID());
|
||||||
|
Files.createDirectory(configMapFolder);
|
||||||
|
Path secret = configMapFolder.resolve(secretFileName);
|
||||||
|
Files.createFile(secret);
|
||||||
|
return configMapFolder;
|
||||||
|
}
|
||||||
|
|
||||||
private static final class WaitingCallback implements Runnable {
|
private static final class WaitingCallback implements Runnable {
|
||||||
|
|
||||||
private final CountDownLatch latch = new CountDownLatch(1);
|
private final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
|
Loading…
Reference in New Issue