Files
kopia/cli/command_snapshot_expire.go
Jarek Kowalski fa7976599c repo: refactored repository interfaces (#780)
- `repo.Repository` is now read-only and only has methods that can be supported over kopia server
- `repo.RepositoryWriter` has read-write methods that can be supported over kopia server
- `repo.DirectRepository` is read-only and contains all methods of `repo.Repository` plus some low-level methods for data inspection
- `repo.DirectRepositoryWriter` contains write methods for `repo.DirectRepository`

- `repo.Reader` removed and merged with `repo.Repository`
- `repo.Writer` became `repo.RepositoryWriter`
- `*repo.DirectRepository` struct became `repo.DirectRepository`
  interface

Getting `{Direct}RepositoryWriter` requires using `NewWriter()` or `NewDirectWriter()` on a read-only repository and multiple simultaneous writers are supported at the same time, each writing to their own indexes and pack blobs.

`repo.Open` returns `repo.Repository` (which is also `repo.RepositoryWriter`).

* content: removed implicit flush on content manager close
* repo: added tests for WriteSession() and implicit flush behavior
* invalidate manifest manager after write session

* cli: disable maintenance in 'kopia server start'
  Server will close the repository before completing.

* repo: unconditionally close RepositoryWriter in {Direct,}WriteSession
* repo: added panic in case somebody tries to create RepositoryWriter after closing repository
  - used atomic to manage SharedManager.closed

* removed stale example
* linter: fixed spurious failures

Co-authored-by: Julio López <julio+gh@kasten.io>
2021-01-20 11:41:47 -08:00

79 lines
2.1 KiB
Go

package cli
import (
"context"
"sort"
"github.com/pkg/errors"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/snapshot"
"github.com/kopia/kopia/snapshot/policy"
)
var (
snapshotExpireCommand = snapshotCommands.Command("expire", "Remove old snapshots according to defined expiration policies.")
snapshotExpireAll = snapshotExpireCommand.Flag("all", "Expire all snapshots").Bool()
snapshotExpirePaths = snapshotExpireCommand.Arg("path", "Expire snapshots for given paths only").Strings()
snapshotExpireDelete = snapshotExpireCommand.Flag("delete", "Whether to actually delete snapshots").Bool()
)
func getSnapshotSourcesToExpire(ctx context.Context, rep repo.Repository) ([]snapshot.SourceInfo, error) {
if *snapshotExpireAll {
return snapshot.ListSources(ctx, rep)
}
var result []snapshot.SourceInfo
for _, p := range *snapshotExpirePaths {
src, err := snapshot.ParseSourceInfo(p, rep.ClientOptions().Hostname, rep.ClientOptions().Username)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse %q", p)
}
result = append(result, src)
}
return result, nil
}
func runExpireCommand(ctx context.Context, rep repo.RepositoryWriter) error {
sources, err := getSnapshotSourcesToExpire(ctx, rep)
if err != nil {
return err
}
sort.Slice(sources, func(i, j int) bool {
return sources[i].String() < sources[j].String()
})
for _, src := range sources {
deleted, err := policy.ApplyRetentionPolicy(ctx, rep, src, *snapshotExpireDelete)
if err != nil {
return errors.Wrapf(err, "error applying retention policy to %v", src)
}
if len(deleted) == 0 {
log(ctx).Infof("Nothing to delete for %v.", src)
continue
}
if *snapshotExpireDelete {
log(ctx).Infof("Deleted %v snapshots of %v...", len(deleted), src)
} else {
log(ctx).Infof("%v snapshot(s) of %v would be deleted. Pass --delete to do it.", len(deleted), src)
for _, it := range deleted {
log(ctx).Infof(" %v", formatTimestamp(it.StartTime))
}
}
}
return nil
}
func init() {
snapshotExpireCommand.Action(repositoryWriterAction(runExpireCommand))
}