mirror of https://github.com/micromata/borgbackup-butler.git

...
Kai Reinhard
14.56.2018 19732b785f222871a76f931213587b2c04cc1e10
...
1 files renamed
14 files modified
232 ■■■■ changed files
README.adoc 21 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java 41 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java 58 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/BorgRepoConfig.java 4 ●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java 6 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/data/Repository.java 14 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgArchive.java 6 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgArchiveInfo.java 6 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgRepoInfo.java 6 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgRepoList.java 6 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgRepository.java 28 ●●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java 20 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx 12 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/repos/RepoCard.jsx 2 ●●● patch | view | raw | blame | history
borgbutler-webapp/src/containers/WebApp.jsx 2 ●●●●● patch | view | raw | blame | history
README.adoc
@@ -16,14 +16,14 @@
{
  "cache_archive_content_max_disc_size_mb" : 1000,
  "repo-configs" : [ {
    "name" : "My-Laptop-Local-Backup",
    "repo" : "/Volumes/backup/my-laptop-backup",
    "display_name" : "My-Laptop-Local-Backup",
    "repo"         : "/Volumes/backup/my-laptop-backup",
  },
  {
    "name" : "My-Laptop-Remote-Backup",
    "repo" : "ssh://backup.acme.com/./backups/my-laptop",
    "display_name"    : "My-Laptop-Remote-Backup",
    "repo"            : "ssh://backup.acme.com/./backups/my-laptop",
    "passwordCommand" : "security find-generic-password -a $USER -s borg-passphrase -w",
    "rsh" : "ssh -i /Users/horst/.ssh/acme_rsa"
    "rsh"             : "ssh -i /Users/horst/.ssh/acme_rsa"
  } ]
}
----
@@ -47,13 +47,14 @@
=== Work with borgbutler-server
==== npm
1. `gradle npmBuild`
2. `cd borgbutler-webapp`
3. `npm install`
4. `npm start`
5. Start borgbutler-server's Main.
1. `cd borgbutler-webapp`
2. `npm install`
3. `npm start`
4. Start borgbutler-server's Main.
=== Ideas
==== 2 factor authentication
https://github.com/j256/two-factor-auth
=== Install server
==== Debian
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
@@ -8,9 +8,12 @@
import de.micromata.borgbutler.json.JsonUtils;
import de.micromata.borgbutler.json.borg.*;
import de.micromata.borgbutler.utils.DateUtils;
import org.apache.commons.exec.*;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.exec.environment.EnvironmentUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,10 +29,10 @@
    private static Logger log = LoggerFactory.getLogger(BorgCommands.class);
    /**
     * Executes borg info repository
     * Executes borg info repository.
     *
     * @param repoConfig
     * @return Parsed repo config returned by Borg command.
     * @return Parsed repo config returned by Borg command (without archives).
     */
    public static Repository info(BorgRepoConfig repoConfig) {
        String json = execute(repoConfig, "info", repoConfig.getRepo(), "--json");
@@ -37,27 +40,42 @@
            return null;
        }
        BorgRepoInfo repoInfo = JsonUtils.fromJson(BorgRepoInfo.class, json);
        repoInfo.setOriginalJson(json);
        Repository repository = new Repository();
        BorgRepository borgRepository = repoInfo.getRepository();
        repository.setId(borgRepository.getId())
        Repository repository = new Repository()
                .setId(borgRepository.getId())
                .setName(repoConfig.getRepo())
                .setDisplayName(repoConfig.getDisplayName())
                .setLastModified(DateUtils.get(borgRepository.getLastModified()))
                .setLocation(borgRepository.getLocation())
                .setName(borgRepository.getName())
                .setCache(repoInfo.getCache())
                .setEncryption(repoInfo.getEncryption())
                .setSecurityDir(repoInfo.getSecurityDir());
        return repository;
    }
    public static BorgRepoList list(BorgRepoConfig repoConfig) {
        String json = execute(repoConfig, "list", repoConfig.getRepo(), "--json");
    /**
     * Executes borg list repository.
     * The given repository will be cloned and archives will be added.
     * The field {@link Repository#getLastModified()} of masterRepository will be updated.
     *
     * @param masterRepository Repository without archives.
     * @return Parsed repo config returned by Borg command including archives.
     */
    public static Repository list(BorgRepoConfig repoConfig, Repository masterRepository) {
        String json = execute(repoConfig, "list", masterRepository.getName(), "--json");
        if (json == null) {
            log.error("Can't load archives from repo '" + masterRepository.getName() + "'.");
            return null;
        }
        BorgRepoList repoList = JsonUtils.fromJson(BorgRepoList.class, json);
        repoList.setOriginalJson(json);
        return repoList;
        if (repoList == null) {
            log.error("Can't load archives from repo '" + masterRepository.getName() + "'.");
            return null;
        }
        masterRepository.setLastModified(repoList.getRepository().getLastModified());
        Repository repository = ObjectUtils.clone(masterRepository)
                .setArchives(repoList.getArchives());
        return repository;
    }
    /**
@@ -73,7 +91,6 @@
            return null;
        }
        BorgArchiveInfo archiveInfo = JsonUtils.fromJson(BorgArchiveInfo.class, json);
        archiveInfo.setOriginalJson(json);
        return archiveInfo;
    }
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -7,11 +7,9 @@
import de.micromata.borgbutler.data.Repository;
import de.micromata.borgbutler.json.borg.BorgArchive;
import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
import de.micromata.borgbutler.json.borg.BorgRepoList;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.jcs.JCS;
import org.apache.commons.jcs.access.CacheAccess;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,24 +38,53 @@
     */
    public Repository getRepository(String idOrName) {
        BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(idOrName);
        if (repoConfig != null) {
            return getRepository(repoConfig);
        }
        List<Repository> repositories = getAllRepositories();
        if (CollectionUtils.isNotEmpty(repositories)) {
            for (Repository repository : repositories) {
                if (StringUtils.equals(idOrName, repository.getName()) || StringUtils.equals(idOrName, repository.getId())) {
                    return repository;
                }
            }
        }
        log.warn("Repo with id or name '" + idOrName + "' not found.");
        return null;
    }
    /**
     * @param repoConfig
     * @return Repository without list of archives.
     */
    private Repository getRepository(BorgRepoConfig repoConfig) {
        Repository repository = repoCacheAccess.get(repoConfig.getRepo());
        if (repository == null || repository.getLocation() == null) {
            repository = BorgCommands.info(repoConfig);
            repoCacheAccess.put(repoConfig.getRepo(), repository);
        }
        if (repository == null) {
            log.warn("Repo with name '" + idOrName + "' not found.");
            log.warn("Repo with name '" + repoConfig.getRepo() + "' not found.");
        }
        return repository;
    }
    private BorgRepoConfig getBorgRepoConfig(String name) {
        for (BorgRepoConfig repoConfig : ConfigurationHandler.getConfiguration().getRepoConfigs()) {
            if (StringUtils.equals(repoConfig.getRepo(), name))
                return repoConfig;
        }
        log.error("Repo config with name '" + name + "' not found.");
        return null;
    }
    /**
     * @return the list of all repositories without the list of archives.
     */
    public List<Repository> getAllRepositories() {
        List<Repository> repositories = new ArrayList<>();
        for (BorgRepoConfig repoConfig : ConfigurationHandler.getConfiguration().getRepoConfigs()) {
            Repository repository = getRepository(repoConfig.getName());
            Repository repository = getRepository(repoConfig);
            if (repository == null) {
                continue;
            }
@@ -84,25 +111,16 @@
     * @return The repository including all archives.
     */
    public Repository getRepositoryArchives(String idOrName) {
        BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(idOrName);
        //ArchiveInfo archiveInfo = BorgCommands.info(repoConfig, repoConfig.getRepo());
        Repository plainRepository = repoArchivesCacheAccess.get(repoConfig.getRepo());
        if (plainRepository != null) {
            return plainRepository;
        }
        plainRepository = repoCacheAccess.get(repoConfig.getRepo());
        if (plainRepository == null) {
            log.warn("Repo with name '" + idOrName + "' not found.");
        Repository masterRepository = getRepository(idOrName);
        if (masterRepository == null) {
            return null;
        }
        BorgRepoList repoList = BorgCommands.list(repoConfig);
        if (repoList == null) {
            log.warn("Repo with name '" + idOrName + "' not found.");
            return null;
        Repository repository = repoArchivesCacheAccess.get(masterRepository.getName());
        if (repository != null) {
            return repository;
        }
        Repository repository = ObjectUtils.clone(plainRepository);
        repository.setArchives(repoList.getArchives());
        repoArchivesCacheAccess.put(repoConfig.getRepo(), repository);
        repository = BorgCommands.list(getBorgRepoConfig(masterRepository.getName()), masterRepository);
        repoArchivesCacheAccess.put(repository.getName(), repository);
        return repository;
    }
borgbutler-core/src/main/java/de/micromata/borgbutler/config/BorgRepoConfig.java
@@ -1,5 +1,6 @@
package de.micromata.borgbutler.config;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@@ -8,7 +9,8 @@
     * A name describing this config. Only used for displaying purposes.
     */
    @Getter @Setter
    private String name;
    @JsonProperty("display_name")
    private String displayName;
    @Getter @Setter
    private String repo;
    @Getter @Setter
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
@@ -24,12 +24,12 @@
        repoConfigs.add(repoConfig);
    }
    public BorgRepoConfig getRepoConfig(String idOrName) {
        if (idOrName == null) {
    public BorgRepoConfig getRepoConfig(String name) {
        if (name == null) {
            return null;
        }
        for (BorgRepoConfig repoConfig : repoConfigs) {
            if (idOrName.equals(repoConfig.getRepo()) ||idOrName.equals(repoConfig.getName())) {
            if (name.equals(repoConfig.getRepo())) {
                return repoConfig;
            }
        }
borgbutler-core/src/main/java/de/micromata/borgbutler/data/Repository.java
@@ -16,14 +16,22 @@
public class Repository implements Serializable, Cloneable {
    private static final long serialVersionUID = 1278802519434516280L;
    /**
     * A name describing this config. Only used for displaying purposes. This is automatically set with the name
     * of the repository configuration.
     * The repo configured for borg.
     *
     * @see BorgRepoConfig#getName()
     * @see BorgRepoConfig#getRepo()
     */
    @Getter
    @Setter
    String name;
    /**
     * A name describing this config. Only used for displaying purposes. This is automatically set with the name
     * of the repository configuration.
     *
     * @see BorgRepoConfig#getDisplayName()
     */
    @Getter
    @Setter
    String displayName;
    @Getter
    @Setter
    private String id;
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgArchive.java
@@ -1,9 +1,7 @@
package de.micromata.borgbutler.json.borg;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.micromata.borgbutler.json.JsonUtils;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@@ -24,10 +22,6 @@
    private String start;
    @Getter
    private String time;
    @Getter
    @Setter
    @JsonIgnore
    private String originalJson;
    public String toString() {
        return JsonUtils.toJson(this, true);
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgArchiveInfo.java
@@ -1,8 +1,6 @@
package de.micromata.borgbutler.json.borg;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@@ -20,8 +18,4 @@
    private BorgEncryption encryption;
    @Getter
    private BorgRepository repository;
    @Getter
    @Setter
    @JsonIgnore
    private String originalJson;
}
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgRepoInfo.java
@@ -1,9 +1,7 @@
package de.micromata.borgbutler.json.borg;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@@ -21,8 +19,4 @@
    private BorgEncryption encryption;
    @Getter
    private BorgRepository repository;
    @Getter
    @Setter
    @JsonIgnore
    protected String originalJson;
}
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgRepoList.java
@@ -1,8 +1,6 @@
package de.micromata.borgbutler.json.borg;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@@ -18,8 +16,4 @@
    private BorgEncryption encryption;
    @Getter
    private BorgRepository repository;
    @Getter
    @Setter
    @JsonIgnore
    protected String originalJson;
}
borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgRepository.java
@@ -1,10 +1,7 @@
package de.micromata.borgbutler.json.borg;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@@ -13,15 +10,6 @@
 */
public class BorgRepository implements Serializable {
    private static final long serialVersionUID = 1278802519434516280L;
    /**
     * A name describing this config. Only used for displaying purposes. This is automatically set with the name
     * of the repository configuration.
     *
     * @see BorgRepoConfig#getName()
     */
    @Getter
    @Setter
    String name;
    @Getter
    private String id;
    @Getter
@@ -29,20 +17,4 @@
    private String lastModified;
    @Getter
    private String location;
    /**
     * Sets also the name for this repository if available in the configuration.
     *
     * @param location
     * @return
     */
    public BorgRepository setLocation(String location) {
        this.location = location;
        // It's ugly but efficiently ;-)
        BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(location);
        if (repoConfig != null) {
            this.name = repoConfig.getName();
        }
        return this;
    }
}
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java
@@ -24,16 +24,32 @@
    @Produces(MediaType.APPLICATION_JSON)
    /**
     *
     * @param id
     * @param id id or name of repo.
     * @param prettyPrinter If true then the json output will be in pretty format.
     * @return Repository (without list of archives) as json string.
     * @see JsonUtils#toJson(Object, boolean)
     */
    public String getTemplate(@QueryParam("id") String id, @QueryParam("prettyPrinter") boolean prettyPrinter) {
    public String getRepo(@QueryParam("id") String id, @QueryParam("prettyPrinter") boolean prettyPrinter) {
        Repository repository = ButlerCache.getInstance().getRepository(id);
        return JsonUtils.toJson(repository, prettyPrinter);
    }
    @GET
    @Path("repoArchiveList")
    @Produces(MediaType.APPLICATION_JSON)
    /**
     *
     * @param id id or name of repo.
     * @param prettyPrinter If true then the json output will be in pretty format.
     * @return Repository (including list of archives) as json string.
     * @see JsonUtils#toJson(Object, boolean)
     */
    public String getRepoArchiveList(@QueryParam("id") String id, @QueryParam("prettyPrinter") boolean prettyPrinter) {
        Repository repository = ButlerCache.getInstance().getRepositoryArchives(id);
        return JsonUtils.toJson(repository, prettyPrinter);
    }
    @GET
    @Path("list")
    @Produces(MediaType.APPLICATION_JSON)
    /**
borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx
File was renamed from borgbutler-webapp/src/components/views/repos/RepoArchiveList.jsx
@@ -4,7 +4,7 @@
import ErrorAlert from '../../general/ErrorAlert';
import {IconRefresh} from "../../general/IconComponents";
class RepoListView extends React.Component {
class RepoArchiveListView extends React.Component {
    path = getRestServiceUrl('repos');
@@ -74,14 +74,6 @@
                >
                    <IconRefresh/>
                </div>
                <CardDeck>
                {this.state.repos.map(repo => {
                    return <RepoCard
                        key={repo.id}
                        repo={repo}
                    />;
                })}
                </CardDeck>
            </React.Fragment>;
        }
@@ -101,4 +93,4 @@
    }
}
export default RepoListView;
export default RepoArchiveListView;
borgbutler-webapp/src/components/views/repos/RepoCard.jsx
@@ -19,7 +19,7 @@
        let repoText = this.buildItem(null, content);
        return <React.Fragment>
            <Card tag={Link} to={`/repos/${repo.id}`} outline color="success" className={'repo'}
            <Card tag={Link} to={`/repoArchives/${repo.id}`} outline color="success" className={'repo'}
                  style={{backgroundColor: '#fff'}}>
                <CardHeader>{repo.name}</CardHeader>
                <CardBody>
borgbutler-webapp/src/containers/WebApp.jsx
@@ -6,6 +6,7 @@
import Menu from '../components/general/Menu';
import Start from '../components/views/Start';
import RepoListView from '../components/views/repos/RepoListView';
import RepoArchiveListView from '../components/views/repos/RepoArchiveListView';
import ConfigurationPage from '../components/views/config/ConfigurationPage';
import RestServices from '../components/views/develop/RestServices';
import {isDevelopmentMode} from '../utilities/global';
@@ -50,6 +51,7 @@
                                    />
                                ))
                            }
                            <Route path={'/repoArchives/:repoId'} component={RepoArchiveListView}/>
                        </Switch>
                    </div>
                    <Footer versionInfo={this.props.version}/>