borgbutler-core/README.adoc
New file @@ -0,0 +1,16 @@ Micromata BorgBackup-Butler =========================== Micromata GmbH, Kai Reinhard :toc: :toclevels: 4 Copyright (C) 2019 ifdef::env-github,env-browser[:outfilesuffix: .adoc] == Development === Creating test data 1. Install virtual debian system 2. `apt install net-tools curl` 3. Execute script `./createFiles.sh` on debian host (borg is installed automatically) 4. See the result files in `out.tar`. borgbutler-core/demo/createFiles.sh
New file @@ -0,0 +1,70 @@ #!/bin/bash export BORG_PASSPHRASE='borgbutler123' export BORG_COMMAND='/root/bin/borg-linux64.dms' export TEST_DIR='/root/borgbutler-demo' if [ -f $BORG_COMMAND ]; then echo Borg command already exists... else echo Downloading borg; mkdir /root/bin cd /root/bin curl -L https://sourceforge.net/projects/borgbutler/files/borg-binaries/borg-linux64.dms/download >$BORG_COMMAND chmod 700 $BORG_COMMAND fi; echo Creating backup dir /backup-test... rm -rf /backup-test mkdir /backup-test echo Initializing borg backup... $BORG_COMMAND init --encryption=repokey /backup-test function backup() { echo Creating backup... $BORG_COMMAND create --filter AME \ --stats \ --progress \ --show-rc \ --compression lz4 \ --exclude-caches \ /backup-test::borgbutlerdemo-$1 \ /home /root /etc /usr/bin /usr/sbin /opt } rm -rf $TEST_DIR mkdir $TEST_DIR cd $TEST_DIR touch README.txt chmod 700 README.txt echo `ls /usr` > filelist touch oldfile backup 2019-01-12_01-00 rm oldfile mkdir newDir touch newDir/newfile chown borgbutler.users README.txt chmod 755 README.txt echo `ls /` >> filelist backup 2019-01-13_01-00 cd /root rm -rf out mkdir out cd out $BORG_COMMAND info --json /backup-test >repo-info.json $BORG_COMMAND list --json /backup-test >repo-list.json $BORG_COMMAND info --json /backup-test::borgbutlerdemo-2019-01-12_01-00 >archive-info-borgbuterldemo-2019-01-12_01-00.json $BORG_COMMAND info --json /backup-test::borgbutlerdemo-2019-01-13_01-00 >archive-info-borgbuterldemo-2019-01-13_01-00.json $BORG_COMMAND list --json-lines /backup-test::borgbutlerdemo-2019-01-12_01-00 >archive-list-borgbuterldemo-2019-01-12_01-00.json $BORG_COMMAND list --json-lines /backup-test::borgbutlerdemo-2019-01-13_01-00 >archive-list-borgbuterldemo-2019-01-13_01-00.json gzip -9 * tar cvf out.tar out borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommand.java
@@ -55,7 +55,7 @@ return this; } String getRepoArchive() { public String getRepoArchive() { if (archive == null) { if (repoConfig == null) { return null; borgbutler-core/src/main/java/de/micromata/borgbutler/BorgJob.java
@@ -3,7 +3,9 @@ import de.micromata.borgbutler.config.BorgRepoConfig; import de.micromata.borgbutler.config.ConfigurationHandler; import de.micromata.borgbutler.data.Archive; import de.micromata.borgbutler.demo.DemoRepos; import de.micromata.borgbutler.jobs.AbstractCommandLineJob; import de.micromata.borgbutler.jobs.JobResult; import de.micromata.borgbutler.json.JsonUtils; import de.micromata.borgbutler.json.borg.ProgressInfo; import lombok.AccessLevel; @@ -103,6 +105,14 @@ } @Override public JobResult<String> execute() { if (DemoRepos.isDemo(command.getRepoConfig().getId())) { return DemoRepos.execute(command); } return super.execute(); } @Override public BorgJob<?> clone() { BorgJob<?> clone = new BorgJob<>(); if (command != null) { borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -8,6 +8,7 @@ import de.micromata.borgbutler.data.ArchiveShortInfo; import de.micromata.borgbutler.data.FileSystemFilter; import de.micromata.borgbutler.data.Repository; import de.micromata.borgbutler.demo.DemoRepos; import de.micromata.borgbutler.json.borg.BorgFilesystemItem; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.jcs.JCS; @@ -59,6 +60,9 @@ } } } if (DemoRepos.isDemo(idOrName)) { return DemoRepos.getRepo(idOrName); } log.warn("Repo with id or name '" + idOrName + "' not found."); return null; } @@ -143,6 +147,9 @@ return repository; } BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(repository.getName()); if (repoConfig == null && DemoRepos.isDemo(idOrName)) { repoConfig = DemoRepos.getRepoConfig(idOrName); } BorgCommands.list(repoConfig, repository); updateArchivesCacheStatusAndShortInfos(repository); return repository; borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
@@ -32,6 +32,10 @@ @Getter private int maxArchiveContentCacheCapacityMb = 100; @Getter @Setter private boolean showDemoRepos = true; /** * Default is restore inside BorgButler's home dir (~/.borgbutler/restore). */ @@ -77,5 +81,6 @@ public void copyFrom(Configuration other) { this.borgCommand = other.borgCommand; this.maxArchiveContentCacheCapacityMb = other.maxArchiveContentCacheCapacityMb; this.showDemoRepos = other.showDemoRepos; } } borgbutler-core/src/main/java/de/micromata/borgbutler/demo/DemoRepos.java
New file @@ -0,0 +1,111 @@ package de.micromata.borgbutler.demo; import de.micromata.borgbutler.BorgCommand; import de.micromata.borgbutler.config.BorgRepoConfig; import de.micromata.borgbutler.config.ConfigurationHandler; import de.micromata.borgbutler.config.Definitions; import de.micromata.borgbutler.data.Repository; import de.micromata.borgbutler.jobs.JobResult; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.ArrayList; import java.util.List; public class DemoRepos { private static Logger log = LoggerFactory.getLogger(DemoRepos.class); private static final String DEMO_IDENTIFIER = "borgbutler-demo"; private static final String[] REPOS = {"fast", "slow", "very-slow"}; private static List<Repository> demoRepos; /** * If configured by the user, demo repositories are added to the given list. If not configured this method does nothing. * * @param repositoryList */ public static void addDemoRepos(List<Repository> repositoryList) { if (!ConfigurationHandler.getConfiguration().isShowDemoRepos()) { return; } init(); for (Repository repo : demoRepos) { repositoryList.add(repo); } } public static boolean isDemo(String idOrName) { return StringUtils.startsWith(idOrName, DEMO_IDENTIFIER); } public static Repository getRepo(String idOrName) { if (!isDemo(idOrName)) { log.info("Given idOrName doesn't fit any demo repository: " + idOrName); return null; } init(); for (Repository repo : demoRepos) { if (StringUtils.equals(idOrName, repo.getId())) { return repo; } } return null; } public static BorgRepoConfig getRepoConfig(String idOrName) { BorgRepoConfig repoConfig = new BorgRepoConfig(); Repository repository = getRepo(idOrName); if (repository == null) { log.info("Given idOrName doesn't fit any demo repository: " + idOrName); return null; } repoConfig.setRepo(repository.getName()) .setId(repository.getId()) .setDisplayName(repository.getName()); return repoConfig; } public static JobResult<String> execute(BorgCommand command) { StringBuilder sb = new StringBuilder(); if (command.getArchive() != null) { sb.append("archive-"); } else { sb.append("repo-"); } sb.append(command.getCommand()); if (command.getArchive() != null) { sb.append("-").append(command.getArchive()); } sb.append(".json.gz"); String file = sb.toString(); try (InputStream inputStream = new GzipCompressorInputStream(DemoRepos.class.getResourceAsStream("/demodata/" + file))) { StringWriter writer = new StringWriter(); IOUtils.copy(inputStream, writer, Definitions.STD_CHARSET); return new JobResult<String>().setResultObject(writer.toString()).setStatus(JobResult.Status.OK); } catch (IOException ex) { log.error("Error while reading demo file '" + file + "': " + ex.getMessage() + "."); return null; } } private static void init() { demoRepos = new ArrayList<>(); demoRepos.add(new Repository() .setId(DEMO_IDENTIFIER + "-fast") .setName(DEMO_IDENTIFIER + "-fast") .setDisplayName("Demo repository fast")); demoRepos.add(new Repository() .setId(DEMO_IDENTIFIER + "-slow") .setName(DEMO_IDENTIFIER + "-slow") .setDisplayName("Demo repository slow")); demoRepos.add(new Repository() .setId(DEMO_IDENTIFIER + "-very-slow") .setName(DEMO_IDENTIFIER + "-very-slow") .setDisplayName("Demo repository very-slow")); } } borgbutler-core/src/main/java/de/micromata/borgbutler/jobs/JobResult.java
@@ -7,7 +7,7 @@ public class JobResult<T> { public enum Status {OK, ERROR} @Getter @Setter(AccessLevel.PACKAGE) @Setter private Status status; @Getter @Setter borgbutler-core/src/main/resources/demodata/repo-list.json.gzBinary files differ
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java
@@ -1,12 +1,9 @@ package de.micromata.borgbutler.server; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import de.micromata.borgbutler.cache.ButlerCache; import de.micromata.borgbutler.config.Configuration; import de.micromata.borgbutler.config.ConfigurationHandler; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,16 +12,11 @@ private static Logger log = LoggerFactory.getLogger(ServerConfiguration.class); private final static String[] SUPPORTED_LANGUAGES = {"en", "de"}; public static final int WEBSERVER_PORT_DEFAULT = 9042; private static final boolean SHOW_TEST_DATA_PREF_DEFAULT = false; private static final boolean WEB_DEVELOPMENT_MODE_PREF_DEFAULT = false; private static String applicationHome; private int port = WEBSERVER_PORT_DEFAULT; @Getter @Setter @JsonIgnore private boolean showTestData = SHOW_TEST_DATA_PREF_DEFAULT; private boolean webDevelopmentMode = WEB_DEVELOPMENT_MODE_PREF_DEFAULT; @JsonProperty public String getCacheDir() { @@ -72,7 +64,6 @@ public void copyFrom(ServerConfiguration other) { super.copyFrom(other); this.port = other.port; this.showTestData = other.showTestData; this.webDevelopmentMode = other.webDevelopmentMode; } } borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java
@@ -4,6 +4,7 @@ import de.micromata.borgbutler.data.Repository; import de.micromata.borgbutler.json.JsonUtils; import de.micromata.borgbutler.json.borg.BorgRepository; import de.micromata.borgbutler.demo.DemoRepos; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +31,7 @@ */ public String getList(@QueryParam("prettyPrinter") boolean prettyPrinter) { List<Repository> repositories = ButlerCache.getInstance().getAllRepositories(); DemoRepos.addDemoRepos(repositories); if (CollectionUtils.isEmpty(repositories)) { return "[]"; } borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
@@ -45,6 +45,7 @@ failed: false, port: 9042, webdevelopmentMode: false, showDemoRepos: true, maxArchiveContentCacheCapacityMb: 100, redirect: false, confirmModal: false @@ -73,7 +74,8 @@ var config = { port: this.state.port, maxArchiveContentCacheCapacityMb : this.state.maxArchiveContentCacheCapacityMb, webDevelopmentMode: this.state.webDevelopmentMode webDevelopmentMode: this.state.webDevelopmentMode, showDemoRepos: this.state.showDemoRepos }; return fetch(getRestServiceUrl("configuration/config"), { method: 'POST', @@ -140,6 +142,12 @@ onChange={this.handleTextChange} placeholder="Enter maximum Capacity" hint={`Limits the cache size of archive file lists in the local cache directory: ${this.state.cacheDir}`} /> <FormLabelField label={'Show demo repositories'} fieldLength={2}> <FormCheckbox checked={this.state.showDemoRepos} hint={'If true, some demo repositories are shown for testing the functionality of BorgButler without any further configuration and running borg backups.'} name="showDemoRepos" onChange={this.handleCheckboxChange} /> </FormLabelField> <FormLabelField label={<I18n name={'configuration.webDevelopmentMode'} />} fieldLength={2}> <FormCheckbox checked={this.state.webDevelopmentMode} hintKey={'configuration.webDevelopmentMode.hint'}