| | |
| | | |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | .setId(borgRepository.getId()) |
| | | .setName(repoConfig.getRepo()) |
| | | .setDisplayName(repoConfig.getDisplayName()) |
| | | .setLastModified(DateUtils.get(borgRepository.getLastModified())) |
| | | .setLastModified(DateUtils.format(borgRepository.getLastModified())) |
| | | .setLocation(borgRepository.getLocation()) |
| | | .setCache(repoInfo.getCache()) |
| | | .setEncryption(repoInfo.getEncryption()) |
| | | .setSecurityDir(repoInfo.getSecurityDir()); |
| | | .setSecurityDir(repoInfo.getSecurityDir()) |
| | | .setLastCacheRefresh(DateUtils.format(LocalDateTime.now())); |
| | | return repository; |
| | | } |
| | | |
| | |
| | | log.error("Can't load archives from repo '" + masterRepository.getName() + "'."); |
| | | return null; |
| | | } |
| | | masterRepository.setLastModified(repoList.getRepository().getLastModified()); |
| | | masterRepository.setLastModified(DateUtils.format(repoList.getRepository().getLastModified())) |
| | | .setLastCacheRefresh(DateUtils.format(LocalDateTime.now())); |
| | | Repository repository = ObjectUtils.clone(masterRepository) |
| | | .setArchives(repoList.getArchives()); |
| | | return repository; |
| | |
| | | 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 void clearAllCaches() { |
| | | this.repoCacheAccess.clear(); |
| | | log.info("Clearing repositories cache (with included archives)..."); |
| | | this.repoArchivesCacheAccess.clear(); |
| | | clearRepoCacheAccess(); |
| | | clearRepoArchicesCacheAccess(); |
| | | log.info("Clearing cache with file lists of archives..."); |
| | | this.archiveFilelistCache.removeAllCacheFiles(); |
| | | } |
| | |
| | | this.repoCacheAccess.clear(); |
| | | } |
| | | |
| | | public void clearRepoArchicesCacheAccess() { |
| | | log.info("Clearing repositories cache (with included archives)..."); |
| | | this.repoArchivesCacheAccess.clear(); |
| | | } |
| | | |
| | | /** |
| | | * @param idOrName |
| | | * @return The repository including all archives. |
| | |
| | | if (repository != null) { |
| | | return repository; |
| | | } |
| | | repository = BorgCommands.list(getBorgRepoConfig(masterRepository.getName()), masterRepository); |
| | | BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(masterRepository.getName()); |
| | | repository = BorgCommands.list(repoConfig, masterRepository); |
| | | if (repository == null) return null; |
| | | repoArchivesCacheAccess.put(repository.getName(), repository); |
| | | return repository; |
| | | } |
| | |
| | | import de.micromata.borgbutler.json.JsonUtils; |
| | | import lombok.Getter; |
| | | import org.apache.commons.io.FileUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | |
| | | try { |
| | | String json = FileUtils.readFileToString(configFile, Definitions.STD_CHARSET); |
| | | this.configuration = JsonUtils.fromJson(Configuration.class, json); |
| | | for (BorgRepoConfig repoConfig : this.configuration.getRepoConfigs()) { |
| | | if (StringUtils.isBlank(repoConfig.getDisplayName())) { |
| | | repoConfig.setDisplayName(repoConfig.getRepo()); |
| | | } |
| | | } |
| | | } catch (IOException ex) { |
| | | log.error("Error while trying to read from config file: " + configFile.getAbsolutePath() + ": " + ex.getMessage(), ex); |
| | | return; |
| | |
| | | @Getter |
| | | @Setter |
| | | private String id; |
| | | /** |
| | | * Date given by Borg server. |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private String lastModified; |
| | | /** |
| | | * Last date of getting this object from Borg server. |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private String lastCacheRefresh; |
| | | @Getter |
| | | @Setter |
| | | private String location; |
| | |
| | | import java.time.format.DateTimeFormatter; |
| | | |
| | | public class DateUtils { |
| | | private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | /** |
| | | * @param borgDateTime |
| | | * @return |
| | | */ |
| | | public static String get(String borgDateTime) { |
| | | public static String format(String borgDateTime) { |
| | | LocalDateTime dateTime = LocalDateTime.parse(borgDateTime); |
| | | return dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); |
| | | return format(dateTime); |
| | | } |
| | | |
| | | /** |
| | | * @param dateTime |
| | | * @return |
| | | */ |
| | | public static String format(LocalDateTime dateTime) { |
| | | return dateTime.format(DATE_TIME_FORMATTER); |
| | | } |
| | | } |
| | |
| | | |
| | | @Test |
| | | void parseTest() { |
| | | assertEquals("2018-11-21T22:31:51",DateUtils.get("2018-11-21T22:31:51.000000")); |
| | | assertEquals("2018-11-21 22:31:51",DateUtils.format("2018-11-21T22:31:51.000000")); |
| | | } |
| | | } |
| | |
| | | /** |
| | | * |
| | | * @param id id or name of repo. |
| | | * @param force If true, a reload of all repositories is forced. |
| | | * @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) |
| | |
| | | * @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) { |
| | | public String getRepoArchiveList(@QueryParam("id") String id, @QueryParam("force") boolean force, |
| | | @QueryParam("prettyPrinter") boolean prettyPrinter) { |
| | | if (force) { |
| | | ButlerCache.getInstance().clearRepoArchicesCacheAccess(); |
| | | } |
| | | Repository repository = ButlerCache.getInstance().getRepositoryArchives(id); |
| | | return JsonUtils.toJson(repository, prettyPrinter); |
| | | } |
| | |
| | | public String getList(@QueryParam("force") boolean force, @QueryParam("prettyPrinter") boolean prettyPrinter) { |
| | | if (force) { |
| | | ButlerCache.getInstance().clearRepoCacheAccess(); |
| | | ButlerCache.getInstance().clearRepoArchicesCacheAccess(); |
| | | } |
| | | List<Repository> repositories = ButlerCache.getInstance().getAllRepositories(); |
| | | if (CollectionUtils.isEmpty(repositories)) { |
| | |
| | | |
| | | class RepoArchiveListView extends React.Component { |
| | | |
| | | |
| | | path = getRestServiceUrl('repos'); |
| | | state = { |
| | | id: this.props.match.params.id, |
| | | isFetching: false |
| | | }; |
| | | |
| | |
| | | this.fetchRepos(); |
| | | }; |
| | | |
| | | |
| | | fetchRepos = (force) => { |
| | | this.setState({ |
| | | isFetching: true, |
| | | failed: false, |
| | | repos: undefined |
| | | failed: false |
| | | }); |
| | | fetch(`${this.path}/list?force=${force}`, { |
| | | fetch(getRestServiceUrl('repos/repoArchiveList', { |
| | | id: this.state.id, |
| | | force: force |
| | | }), { |
| | | method: 'GET', |
| | | headers: { |
| | | 'Accept': 'application/json' |
| | |
| | | }) |
| | | .then(response => response.json()) |
| | | .then(json => { |
| | | const repos = json.map(repo => { |
| | | return { |
| | | id: repo.id, |
| | | name: repo.name, |
| | | location: repo.location, |
| | | lastModified: repo.last_modified |
| | | }; |
| | | }); |
| | | |
| | | this.setState({ |
| | | isFetching: false, |
| | | repos |
| | | repo: json |
| | | }) |
| | | }) |
| | | .catch(() => this.setState({isFetching: false, failed: true})); |
| | |
| | | |
| | | render = () => { |
| | | let content = undefined; |
| | | const repo = this.state.repo; |
| | | let pageHeader = ''; |
| | | |
| | | if (this.state.isFetching) { |
| | | |
| | | content = <i>Loading...</i>; |
| | | |
| | | } else if (this.state.failed) { |
| | | |
| | | content = <ErrorAlert |
| | | title={'Cannot load Repositories'} |
| | | description={'Something went wrong during contacting the rest api.'} |
| | |
| | | title: 'Try again' |
| | | }} |
| | | />; |
| | | |
| | | } else if (this.state.repos) { |
| | | |
| | | } else if (this.state.repo) { |
| | | pageHeader = `${repo.displayName}`; |
| | | content = <React.Fragment> |
| | | {repo.displayName} |
| | | <div |
| | | className={'btn btn-outline-primary refresh-button-right'} |
| | | onClick={this.fetchRepos.bind(this, true)} |
| | |
| | | </React.Fragment>; |
| | | |
| | | } |
| | | |
| | | return <React.Fragment> |
| | | <PageHeader> |
| | | Repositories |
| | | {pageHeader} |
| | | </PageHeader> |
| | | {content} |
| | | </React.Fragment>; |
| | |
| | | {repoText} |
| | | </ul> |
| | | </CardBody> |
| | | <CardFooter><span className={'lastModified'}>Last modified: {repo.lastModified}</span></CardFooter> |
| | | <CardFooter><span className={'lastModified'}>Last refresh: {repo.lastCacheRefresh}, last modified: {repo.lastModified}</span></CardFooter> |
| | | </Card> |
| | | </React.Fragment> |
| | | }; |
| | |
| | | /> |
| | | )) |
| | | } |
| | | <Route path={'/repoArchives/:repoId'} component={RepoArchiveListView}/> |
| | | <Route path={'/repoArchives/:id'} component={RepoArchiveListView}/> |
| | | </Switch> |
| | | </div> |
| | | <Footer versionInfo={this.props.version}/> |