borgbutler-core/src/main/kotlin/de/micromata/borgbutler/config/Configuration.kt
@@ -30,8 +30,6 @@ /** * The borg version to install from github (optional). */ // @JsonIgnore needed by client: ConfigurationserverTab.jsx fails otherwise (conflicting borgVersion fields). @JsonIgnore var borgVersion: String? = null /** @@ -101,6 +99,7 @@ fun copyFrom(other: Configuration) { borgCommand = other.borgCommand borgVersion = other.borgVersion maxArchiveContentCacheCapacityMb = other.maxArchiveContentCacheCapacityMb showDemoRepos = other.showDemoRepos } @@ -123,6 +122,10 @@ return this } override fun toString(): String { return "borgCommand=[$borgCommand], borgVersion=[$borgVersion], workingDir=[$workingDir], maxArchiveContentCacheCapacityMb=[$maxArchiveContentCacheCapacityMb], showDemoRepos=[$showDemoRepos]" } companion object { /** * Default dir name for restoring archives. borgbutler-core/src/test/resources/log4j.properties
@@ -1,5 +1,4 @@ log4j.rootLogger=info, stdout log4j.logger.de.micromata.paypal=debug log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgConfig.java
File was renamed from borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java @@ -2,12 +2,8 @@ import org.apache.commons.lang3.StringUtils; public class BorgVersion { public static final String BORG_DEFAULT_DOWNLOAD_VERSION = "1.1.16"; private static final String BORG_VERSION = BORG_DEFAULT_DOWNLOAD_VERSION; private String binariesDownloadVersion = BORG_DEFAULT_DOWNLOAD_VERSION; public class BorgConfig { public static final String BORG_DEFAULT_DOWNLOAD_VERSION = "1.1.17"; private String[][] borgBinaries = { {"freebsd64", "FreeBSD 64"}, @@ -18,7 +14,7 @@ private String minimumRequiredBorgVersion = "1.1.8"; public String getBinariesDownloadUrl() { return "https://github.com/borgbackup/borg/releases/download/" + binariesDownloadVersion + "/"; return "https://github.com/borgbackup/borg/releases/download/" + version + "/"; } /** @@ -28,10 +24,10 @@ private String borgBinary; private boolean versionOK = false; private String version; private String version = BORG_DEFAULT_DOWNLOAD_VERSION; private String statusMessage; public BorgVersion copyFrom(BorgVersion other) { public BorgConfig copyFrom(BorgConfig other) { this.borgBinary = other.borgBinary; this.versionOK = other.versionOK; this.version = other.version; @@ -39,18 +35,6 @@ return this; } public String getBinariesDownloadVersion() { return this.binariesDownloadVersion; } public void setBinariesDownloadVersion(String binariesDownloadVersion) { if (StringUtils.isNotBlank(binariesDownloadVersion)) { this.binariesDownloadVersion = binariesDownloadVersion; } else { this.binariesDownloadVersion = BORG_DEFAULT_DOWNLOAD_VERSION; } } public String[][] getBorgBinaries() { return this.borgBinaries; } @@ -78,22 +62,26 @@ return this.statusMessage; } BorgVersion setBorgBinary(String borgBinary) { BorgConfig setBorgBinary(String borgBinary) { this.borgBinary = borgBinary; return this; } BorgVersion setVersionOK(boolean versionOK) { BorgConfig setVersionOK(boolean versionOK) { this.versionOK = versionOK; return this; } BorgVersion setVersion(String version) { this.version = version; BorgConfig setVersion(String version) { if (StringUtils.isNotBlank(version)) { this.version = version; } else { this.version = BORG_DEFAULT_DOWNLOAD_VERSION; } return this; } BorgVersion setStatusMessage(String statusMessage) { BorgConfig setStatusMessage(String statusMessage) { this.statusMessage = statusMessage; return this; } @@ -125,4 +113,14 @@ } return version.split("\\."); } @Override public String toString() { return "BorgConfig{" + ", borgBinary='" + borgBinary + '\'' + ", versionOK=" + versionOK + ", version='" + version + '\'' + ", statusMessage='" + statusMessage + '\'' + '}'; } } borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
@@ -26,7 +26,7 @@ return instance; } private BorgVersion borgVersion = new BorgVersion(); private BorgConfig borgConfig = new BorgConfig(); public void initialize() { Configuration configuration = ConfigurationHandler.getConfiguration(); @@ -35,10 +35,10 @@ return; } } borgVersion.setBinariesDownloadVersion(configuration.getBorgVersion()); borgConfig.setVersion(configuration.getBorgVersion()); initialize(getBinary(RunningMode.getOSType())); if (!borgVersion.isVersionOK()) { log.warn("No working borg version found. Please configure a borg version with minimal version '" + borgVersion.getMinimumRequiredBorgVersion() + "'."); if (!borgConfig.isVersionOK()) { log.warn("No working borg version found. Please configure a borg version with minimal version '" + borgConfig.getMinimumRequiredBorgVersion() + "'."); } } @@ -46,13 +46,19 @@ * Configures a new borg configuration if modifications was done. * * @param newConfiguration The new configuration with the (new) borg command to use (executable). * @param borgBinary The id of the borg binary (Mac OS X, Linux 64, manual etc.) * @param newBorgConfig The new config, including the id of the borg binary (Mac OS X, Linux 64, manual etc.) and version. */ public void configure(ServerConfiguration newConfiguration, String borgBinary) { public void configure(ServerConfiguration newConfiguration, BorgConfig newBorgConfig) { ServerConfiguration configuration = ServerConfiguration.get(); boolean borgBinaryChanged = !StringUtils.equals(borgVersion.getBorgBinary(), borgBinary); borgVersion.setBorgBinary(borgBinary); // Update borg binary (if changed). boolean manualBorgCommand = "manual".equals(borgBinary); String oldBorgBinary = borgConfig.getBorgBinary(); String oldVersion = borgConfig.getVersion(); String newBorgBinary = newBorgConfig.getBorgBinary(); String newVersion = newConfiguration.getBorgVersion(); boolean borgBinaryChanged = !StringUtils.equals(oldBorgBinary, newBorgBinary) || !StringUtils.equals(oldVersion, newVersion); borgConfig.setBorgBinary(newBorgBinary); // Update borg binary (if changed). borgConfig.setVersion(newVersion); boolean manualBorgCommand = "manual".equals( newBorgConfig.getBorgBinary()); if (manualBorgCommand) { boolean borgCommandChanged = !StringUtils.equals(newConfiguration.getBorgCommand(), configuration.getBorgCommand()); if (borgCommandChanged) { @@ -61,9 +67,16 @@ } } else { if (borgBinaryChanged) { initialize(getBinary(borgBinary)); initialize(getBinary(newBorgBinary)); } newConfiguration.setBorgCommand(configuration.getBorgCommand()); // borg command of this class overwrites new configuration for mode != 'manual'. newConfiguration.setBorgVersion(newVersion); if (!StringUtils.equals(oldVersion, newVersion)) { log.info("Version '" + oldVersion + "' -> '" + newVersion + "'."); } if (!StringUtils.equals(oldBorgBinary, newBorgBinary)) { log.info("Binary '" + oldBorgBinary + "' -> '" + newBorgBinary + "'."); } } } @@ -75,7 +88,7 @@ File file = download(binary); if (file != null) { configuration.setBorgCommand(file.getAbsolutePath()); borgVersion.setBorgBinary(binary[0]); borgConfig.setBorgBinary(binary[0]); } return version(configuration); } @@ -83,9 +96,9 @@ private boolean version(Configuration configuration) { String borgCommand = configuration.getBorgCommand(); if (StringUtils.isNotBlank(borgCommand)) { for (String[] borgBinary : borgVersion.getBorgBinaries()) { for (String[] borgBinary : borgConfig.getBorgBinaries()) { if (borgCommand.contains(borgBinary[0])) { borgVersion.setBorgBinary(borgBinary[0]); borgConfig.setBorgBinary(borgBinary[0]); break; } } @@ -94,22 +107,22 @@ boolean versionOK = false; String msg = null; if (versionString != null) { borgVersion.setVersion(versionString); int cmp = BorgVersion.compareVersions(versionString, borgVersion.getMinimumRequiredBorgVersion()); borgConfig.setVersion(versionString); int cmp = BorgConfig.compareVersions(versionString, borgConfig.getMinimumRequiredBorgVersion()); if (cmp < 0) { msg = "Found borg version '" + versionString + "' is less than minimum required version '" + borgVersion.getMinimumRequiredBorgVersion() + "'."; msg = "Found borg version '" + versionString + "' is less than minimum required version '" + borgConfig.getMinimumRequiredBorgVersion() + "'."; log.info(msg); } else { versionOK = true; msg = "Found borg '" + configuration.getBorgCommand() + "', version: " + versionString + " (equals to or newer than '" + borgVersion.getMinimumRequiredBorgVersion() msg = "Found borg '" + configuration.getBorgCommand() + "', version: " + versionString + " (equals to or newer than '" + borgConfig.getMinimumRequiredBorgVersion() + "', OK)."; log.info(msg); } } else { msg = "Couldn't execute borg command '" + configuration.getBorgCommand() + "'."; } borgVersion.setVersionOK(versionOK); borgVersion.setStatusMessage(msg); borgConfig.setVersionOK(versionOK); borgConfig.setStatusMessage(msg); return versionOK; } @@ -133,7 +146,7 @@ if (os == null) { return null; } for (String[] binary : borgVersion.getBorgBinaries()) { for (String[] binary : borgConfig.getBorgBinaries()) { if (binary[0].contains(os)) { return binary; } @@ -156,7 +169,7 @@ // File already downloaded, nothing to do. return file; } String url = borgVersion.getBinariesDownloadUrl() + getDownloadFilename(binary); String url = borgConfig.getBinariesDownloadUrl() + getDownloadFilename(binary); log.info("Trying to download borg binary '" + binary[0] + "' (" + binary[1] + ") from url: " + url + "..."); HttpClientBuilder builder = HttpClients.custom() .setDefaultRequestConfig(RequestConfig.custom() @@ -186,7 +199,7 @@ log.info("Creating binary directory: " + dir.getAbsolutePath()); dir.mkdirs(); } return new File(dir, getDownloadFilename(binary) + "-" + borgVersion.getBinariesDownloadVersion()); return new File(dir, getDownloadFilename(binary) + "-" + borgConfig.getVersion()); } private String getDownloadFilename(String[] binary) { @@ -196,7 +209,7 @@ private BorgInstallation() { } public BorgVersion getBorgVersion() { return this.borgVersion; public BorgConfig getBorgConfig() { return this.borgConfig; } } borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/ServerConfiguration.kt
@@ -20,6 +20,10 @@ webDevelopmentMode = other.webDevelopmentMode } override fun toString(): String { return "${super.toString()}, port=[$port], webDevelopmentMode=[$webDevelopmentMode]" } companion object { val supportedLanguages = arrayOf("en", "de") const val WEBSERVER_PORT_DEFAULT = 9042 borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationInfo.kt
@@ -1,9 +1,9 @@ package de.micromata.borgbutler.server.rest import de.micromata.borgbutler.server.BorgVersion import de.micromata.borgbutler.server.BorgConfig import de.micromata.borgbutler.server.ServerConfiguration class ConfigurationInfo( var serverConfiguration: ServerConfiguration? = null, var borgVersion: BorgVersion? = null var borgConfig: BorgConfig? = null ) borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationRest.kt
@@ -2,13 +2,11 @@ import de.micromata.borgbutler.cache.ButlerCache import de.micromata.borgbutler.config.ConfigurationHandler import de.micromata.borgbutler.json.JsonUtils import de.micromata.borgbutler.server.BorgInstallation import de.micromata.borgbutler.server.ServerConfiguration import de.micromata.borgbutler.server.user.UserData import de.micromata.borgbutler.server.user.UserManager import mu.KotlinLogging import org.apache.commons.lang3.StringUtils import org.springframework.web.bind.annotation.* private val log = KotlinLogging.logger {} @@ -21,19 +19,19 @@ fun getConfig(): ConfigurationInfo { val configurationInfo = ConfigurationInfo() configurationInfo.serverConfiguration = ServerConfiguration.get() configurationInfo.borgVersion = BorgInstallation.getInstance().borgVersion configurationInfo.borgConfig = BorgInstallation.getInstance().borgConfig return configurationInfo } @PostMapping("config") fun setConfig(@RequestBody configurationInfo: ConfigurationInfo) { val configurationHandler = ConfigurationHandler.getInstance() BorgInstallation.getInstance() .configure(configurationInfo.serverConfiguration, configurationInfo.borgVersion?.borgBinary) log.info("server-config: ${configurationInfo.serverConfiguration}, borg-binary: ${configurationInfo.borgConfig?.borgBinary}") BorgInstallation.getInstance().configure(configurationInfo.serverConfiguration, configurationInfo.borgConfig) val configuration: ServerConfiguration = ServerConfiguration.get() configurationInfo.serverConfiguration?.let { configuration.copyFrom(it) } val configurationHandler = ConfigurationHandler.getInstance() configurationHandler.save() } borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfo.kt
@@ -1,7 +1,7 @@ package de.micromata.borgbutler.server.rest import de.micromata.borgbutler.BorgQueueStatistics import de.micromata.borgbutler.server.BorgVersion import de.micromata.borgbutler.server.BorgConfig /** * Statistics of all the job queues, especially the number of total queued and running jobs. @@ -13,7 +13,7 @@ private set var configurationOK = false private set var borgVersion: BorgVersion? = null var borgConfig: BorgConfig? = null private set fun setQueueStatistics(queueStatistics: BorgQueueStatistics?): SystemInfo { @@ -26,8 +26,8 @@ return this } fun setBorgVersion(borgVersion: BorgVersion?): SystemInfo { this.borgVersion = borgVersion fun setBorgConfig(borgConfig: BorgConfig?): SystemInfo { this.borgConfig = borgConfig return this } } borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfoRest.kt
@@ -16,11 +16,11 @@ */ @GetMapping("info") fun statistics(): SystemInfo { val borgVersion = BorgInstallation.getInstance().borgVersion val systemInfonfo = SystemInfo() val borgConfig = BorgInstallation.getInstance().borgConfig val systemInfo = SystemInfo() .setQueueStatistics(BorgQueueExecutor.getInstance().statistics) .setConfigurationOK(borgVersion.isVersionOK) .setBorgVersion(borgVersion) return systemInfonfo .setConfigurationOK(borgConfig.isVersionOK) .setBorgConfig(borgConfig) return systemInfo } } borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgConfigTest.java
New file @@ -0,0 +1,20 @@ package de.micromata.borgbutler.server; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class BorgConfigTest { @Test void versionCompareTest() { Assertions.assertThrows(IllegalArgumentException.class, () -> { BorgConfig.compareVersions(null, ""); }); Assertions.assertThrows(IllegalArgumentException.class, () -> { BorgConfig.compareVersions("", ""); }); Assertions.assertEquals(-1, BorgConfig.compareVersions("1.1.8", "1.1.16")); Assertions.assertEquals(0, BorgConfig.compareVersions("1.1.8", "1.1.8")); Assertions.assertEquals(1, BorgConfig.compareVersions("1.1.16", "1.1.8")); } } borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java
@@ -21,9 +21,24 @@ borgInstallation.initialize(); } @Test void configureTest() { ConfigurationHandler.setConfigClazz(ServerConfiguration.class); BorgInstallation borgInstallation = BorgInstallation.getInstance(); borgInstallation.initialize(); BorgConfig borgConfig = new BorgConfig(); borgConfig.setVersion("1.1.15"); borgConfig.setBorgBinary("freebsd64"); ServerConfiguration serverConfig = ServerConfiguration.get(); borgInstallation.configure(serverConfig, borgConfig); String expected = "freebsd64-1.1.15"; assertTrue(serverConfig.getBorgCommand().endsWith(expected), "String '" + serverConfig.getBorgCommand() + "' should end with '" + expected + "'."); } @Test void downloadTest() { String version = new BorgVersion().getBinariesDownloadVersion(); String version = new BorgConfig().getVersion(); checkDownload(RunningMode.OSType.LINUX, "borg-linux64-" + version); checkDownload(RunningMode.OSType.MAC_OS, "borg-macosx64-" + version); checkDownload(RunningMode.OSType.FREEBSD, "borg-freebsd64-" + version); borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgVersionTest.java
File was deleted borgbutler-server/src/test/kotlin/de/micromata/borgbutler/server/user/UserFilterTest.kt
@@ -1,6 +1,5 @@ package de.micromata.borgbutler.server.user import de.micromata.borgbutler.server.BorgVersion import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
@@ -35,8 +35,8 @@ .then((data) => { this.setState({ loading: false, borgVersion: data.borgVersion, borgBinary: data.borgVersion.borgBinary, borgConfig: data.borgConfig, borgBinary: data.borgConfig.borgBinary, ...data.serverConfiguration }) }) @@ -56,6 +56,7 @@ loading: true, failed: false, port: 9042, borgVersion: "1.1.17", webdevelopmentMode: false, showDemoRepos: true, maxArchiveContentCacheCapacityMb: 100, @@ -88,9 +89,10 @@ maxArchiveContentCacheCapacityMb: this.state.maxArchiveContentCacheCapacityMb, webDevelopmentMode: this.state.webDevelopmentMode, showDemoRepos: this.state.showDemoRepos, borgCommand: this.state.borgCommand borgCommand: this.state.borgCommand, borgVersion: this.state.borgVersion, }, borgVersion: { borgConfig: { borgBinary: this.state.borgBinary } }; @@ -121,12 +123,12 @@ if (this.state.failed) { return <ErrorAlertGenericRestFailure handleClick={this.loadConfig}/>; } const borgVersion = this.state.borgVersion; const borgConfig = this.state.borgConfig; let borgInfoColor = 'success'; let borgInfoMessage = `Borg version '${borgVersion.version}' is OK.`; if (!borgVersion.versionOK) { let borgInfoMessage = `Borg version '${borgConfig.version}' is OK.`; if (!borgConfig.versionOK) { borgInfoColor = 'danger'; borgInfoMessage = borgVersion.statusMessage; borgInfoMessage = borgConfig.statusMessage; } return ( <React.Fragment> @@ -138,9 +140,9 @@ value={this.state.borgBinary} name={'borgBinary'} onChange={this.handleTextChange} hint={`Choose your OS and BorgButler will download and use a ready to run borg binary from ${borgVersion.binariesDownloadUrl} or choose a manual installed version.`} hint={`Choose your OS and BorgButler will download and use a ready to run borg binary from ${borgConfig.binariesDownloadUrl} or choose a manual installed version.`} > {borgVersion.borgBinaries {borgConfig.borgBinaries .map((binary, index) => <FormOption label={binary[1]} value={binary[0]} key={index}/>)} <FormOption label={'Manual'} value={'manual'}/> @@ -157,6 +159,10 @@ {borgInfoMessage} </Alert> </FormGroup> <FormLabelInputField label={'Borg version'} fieldLength={2} name={'borgVersion'} value={this.state.borgVersion} onChange={this.handleTextChange} placeholder="Enter borg version (e. g. 1.1.17)"/> <FormLabelInputField label={'Port'} fieldLength={2} type="number" min={0} max={65535} step={1} name={'port'} value={this.state.port}