Files
kopia/cli/command_snapshot_expire.go
Jarek Kowalski 044db7593b feat(repository): apply retention policies server-side (#3249)
* feat(repository): apply retention policies server-side

This allows append-only snapshots where the client can never delete
arbitrary manifests and policies are maintained on the server.

The client only needs permissions to create snapshots in a given, which
automatically gives them permission to invoke the server-side method
for their own snapshots only.

* Update cli/command_acl_add.go

Co-authored-by: Guillaume <Gui13@users.noreply.github.com>

* Update internal/server/api_manifest.go

Co-authored-by: Guillaume <Gui13@users.noreply.github.com>

* Update internal/server/api_manifest.go

Co-authored-by: Guillaume <Gui13@users.noreply.github.com>

* Update internal/server/grpc_session.go

Co-authored-by: Guillaume <Gui13@users.noreply.github.com>

---------

Co-authored-by: Guillaume <Gui13@users.noreply.github.com>
2023-09-02 18:23:21 -07: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"
)
type commandSnapshotExpire struct {
snapshotExpireAll bool
snapshotExpirePaths []string
snapshotExpireDelete bool
}
func (c *commandSnapshotExpire) setup(svc appServices, parent commandParent) {
cmd := parent.Command("expire", "Remove old snapshots according to defined expiration policies.")
cmd.Flag("all", "Expire all snapshots").BoolVar(&c.snapshotExpireAll)
cmd.Arg("path", "Expire snapshots for given paths only").StringsVar(&c.snapshotExpirePaths)
cmd.Flag("delete", "Whether to actually delete snapshots").BoolVar(&c.snapshotExpireDelete)
cmd.Action(svc.repositoryWriterAction(c.run))
}
func (c *commandSnapshotExpire) getSnapshotSourcesToExpire(ctx context.Context, rep repo.Repository) ([]snapshot.SourceInfo, error) {
if c.snapshotExpireAll {
//nolint:wrapcheck
return snapshot.ListSources(ctx, rep)
}
var result []snapshot.SourceInfo
for _, p := range c.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 (c *commandSnapshotExpire) run(ctx context.Context, rep repo.RepositoryWriter) error {
sources, err := c.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, c.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 c.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)
}
}
return nil
}