github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/cmd/ctr/commands/tasks/delete.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package tasks 18 19 import ( 20 gocontext "context" 21 22 "github.com/containerd/containerd" 23 "github.com/containerd/containerd/cio" 24 "github.com/containerd/containerd/cmd/ctr/commands" 25 "github.com/containerd/containerd/log" 26 "github.com/urfave/cli" 27 ) 28 29 var deleteCommand = cli.Command{ 30 Name: "delete", 31 Usage: "delete one or more tasks", 32 ArgsUsage: "CONTAINER [CONTAINER, ...]", 33 Aliases: []string{"rm"}, 34 Flags: []cli.Flag{ 35 cli.BoolFlag{ 36 Name: "force, f", 37 Usage: "force delete task process", 38 }, 39 cli.StringFlag{ 40 Name: "exec-id", 41 Usage: "process ID to kill", 42 }, 43 }, 44 Action: func(context *cli.Context) error { 45 var ( 46 execID = context.String("exec-id") 47 force = context.Bool("force") 48 ) 49 client, ctx, cancel, err := commands.NewClient(context) 50 if err != nil { 51 return err 52 } 53 defer cancel() 54 var opts []containerd.ProcessDeleteOpts 55 if force { 56 opts = append(opts, containerd.WithProcessKill) 57 } 58 var exitErr error 59 if execID != "" { 60 task, err := loadTask(ctx, client, context.Args().First()) 61 if err != nil { 62 return err 63 } 64 p, err := task.LoadProcess(ctx, execID, nil) 65 if err != nil { 66 return err 67 } 68 status, err := p.Delete(ctx, opts...) 69 if err != nil { 70 return err 71 } 72 if ec := status.ExitCode(); ec != 0 { 73 return cli.NewExitError("", int(ec)) 74 } 75 } else { 76 for _, target := range context.Args() { 77 task, err := loadTask(ctx, client, target) 78 if err != nil { 79 if exitErr == nil { 80 exitErr = err 81 } 82 log.G(ctx).WithError(err).Errorf("failed to load task from %v", target) 83 continue 84 } 85 status, err := task.Delete(ctx, opts...) 86 if err != nil { 87 if exitErr == nil { 88 exitErr = err 89 } 90 log.G(ctx).WithError(err).Errorf("unable to delete %v", task.ID()) 91 continue 92 } 93 if ec := status.ExitCode(); ec != 0 { 94 log.G(ctx).Warnf("task %v exit with non-zero exit code %v", task.ID(), int(ec)) 95 } 96 } 97 } 98 return exitErr 99 }, 100 } 101 102 func loadTask(ctx gocontext.Context, client *containerd.Client, containerID string) (containerd.Task, error) { 103 container, err := client.LoadContainer(ctx, containerID) 104 if err != nil { 105 return nil, err 106 } 107 task, err := container.Task(ctx, cio.Load) 108 if err != nil { 109 return nil, err 110 } 111 return task, nil 112 }