containerd/cmd/dist/delete.go
Stephen J Day 706c629354
api/services/content: define delete method
Allow deletion of content over the GRPC interface. For now, we are going
with a model that conducts reference management outside of the content
store, in the metadata store but this design is valid either way.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-02-27 20:06:29 -08:00

67 lines
1.5 KiB
Go

package main
import (
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
contentapi "github.com/docker/containerd/api/services/content"
"github.com/docker/containerd/log"
digest "github.com/opencontainers/go-digest"
"github.com/urfave/cli"
)
var deleteCommand = cli.Command{
Name: "delete",
Aliases: []string{"delete", "del", "remove", "rm"},
Usage: "permanently delete one or more blobs.",
ArgsUsage: "[flags] [<digest>, ...]",
Description: `Delete one or more blobs permanently. Successfully deleted
blobs are printed to stdout.`,
Flags: []cli.Flag{},
Action: func(context *cli.Context) error {
var (
ctx = background
args = []string(context.Args())
exitError error
)
conn, err := connectGRPC(context)
if err != nil {
return err
}
client := contentapi.NewContentClient(conn)
for _, arg := range args {
dgst, err := digest.Parse(arg)
if err != nil {
if exitError == nil {
exitError = err
}
log.G(ctx).WithError(err).Errorf("could not delete %v", dgst)
continue
}
if _, err := client.Delete(ctx, &contentapi.DeleteContentRequest{
Digest: dgst,
}); err != nil {
switch grpc.Code(err) {
case codes.NotFound:
// if it is already deleted, ignore!
default:
if exitError == nil {
exitError = err
}
log.G(ctx).WithError(err).Errorf("could not delete %v", dgst)
}
continue
}
fmt.Println(dgst)
}
return exitError
},
}