对于将在Synology RS815 + NAS上检查备份文件的Spring Boot应用程序,我们希望能够轻松测试此NAS上存储的文件,而不必复制存储在其上的7TB。
理想情况下,我们希望创建相同的文件结构以在Spring开发配置文件中使用Web应用程序,并在JUnit测试中使用这些文件结构。
介绍FileStructureCreator
我们首先创建一个新的类FileStructureCreator
,如下所示:
- @Getter
- @Setter
- public class FileStructureCreator implements Closeable {
-
- public static final Path baseTestPath = Paths.get("testFiles");
- private Path fileStructureBasePath;
-
- public static FileStructureCreator create(Path file) {
- return createStructure(file, false);
- }
-
- public static FileStructureCreator createTempDirectory(Path file) {
- return createStructure(file, true);
- }
-
- @SneakyThrows
- private static FileStructureCreator createStructure(Path file, boolean createTempDirectory) {
- FileStructureCreator fileStructureCreator = new FileStructureCreator();
-
- if (!Files.exists(baseTestPath)) {
- Files.createDirectory(baseTestPath);
- }
-
- String path = baseTestPath.toString() + (createTempDirectory ? "/" + UUID.randomUUID().toString() : "")
- + "/";
- Path basePath = Paths.get(path);
- fileStructureCreator.setFileStructureBasePath(basePath);
- FileUtils.forceMkdir(basePath.toFile());
-
- try (Stream<String> stream = Files.lines(file)) {
- stream.forEach(line -> {
- Metadata fileMetaData = Metadata.from(line);
-
- Path fileEntry = Paths.get(path + fileMetaData.getWindowsSafeFilename());
- try {
- FileUtils.forceMkdir(fileEntry.getParent().toFile());
- if (!Files.exists(fileEntry)) {
- Files.write(fileEntry, line.getBytes());
- Files.setLastModifiedTime(fileEntry, FileTime.from(fileMetaData.getModificationTime()));
- }
- } catch (IOException ignore) {
- throw new RuntimeException("Exception creating directory: " + fileEntry.getParent());
- }
- });
- }
- return fileStructureCreator;
- }
- @Override
- @SneakyThrows
- public void close() {
- if (fileStructureBasePath != null) {
- FileUtils.deleteDirectory(fileStructureBasePath.toFile());
- }
- }
- }
基本上,这将创建整个目录结构和必要的文件。 我们只需要传递一个包含文件结构元数据的基本文件即可。
元数据保存时间戳,文件大小和该文件的路径。 看起来像这样:
- 2016-04-05T10:30:15.012345678 5120
-
- backupftp/@eaDir/sharesnap_share_configuration/SYNO@.quota
-
- 2018-02-26T00:00:09.012345678 169
-
- backupftp/@eaDir/sharesnap_share_configuration/share_configuration
然后,在Synology NAS上,我们可以通过执行以下命令轻松生成具有(特定)目录的整个树结构的文件:
- find backupftp -type f -printf
- "%TY-%Tm-%TdT%TH:%TM:%.12TS\t%s\t%p\n">test/backupftp.files.txt
将生成的文件从您的Synology NAS复制到您的项目。
在JUnit测试中,我们使用FileStructureCreator
类,如下面的示例所示。 请注意, FileStructureCreator
实现了AutoCloseable
,因此我们可以在测试完成后使用try / catch块来清理文件。
- @Value("classpath:/TestDiskConsistencyPolicy-notEnoughFileSets.txt")
- private Path notEnoughFileSets;
-
- @Test(expected = RuntimeException.class)
- public void backupSetWithNoFileSetsThrowException() {
- try( FileStructureCreator creator = FileStructureCreator.createTempDirectory(notEnoughFileSets) ) {
- BackupSet backupSet = BackupSet.builder().uri(creator.getFileStructureBasePath().toString()).build();
- new DiskConsistencyPolicy(backupSet).execute();
- assertTrue( "Expecting a RuntimeException here", false);
- }
- }
对于Spring Boot应用程序,我们只定义一个@Configuration
类,该类将为Synology NAS上定义的文件共享创建数据结构。
- @Configuration
- @Profile("dev")
- public class TestFilesInstaller {
- @Bean
- public FileStructureCreator ftpFiles(@Value("classpath:/backupftp.files.txt") Path file) {
- return FileStructureCreator.create(file);
- }
- @Bean
- public FileStructureCreator nfsFiles(@Value("classpath:/backupnfs.files.txt") Path file) {
- return FileStructureCreator.create(file);
- }
- }
因为它们被定义为@Bean
,所以在应用程序关闭时将自动调用close()
方法,并在Spring Boot应用程序停止时从磁盘上删除所有文件。
只是……不要在生产环境中运行开发人员资料; 我让你知道会发生什么。 ;-) 将来,我们将向您展示如何构建备份检查器以监视和验证NAS上的备份。