github.com/containerd/Containerd@v1.4.13/cmd/ctr/commands/namespaces/namespaces.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 namespaces 18 19 import ( 20 "fmt" 21 "os" 22 "sort" 23 "strings" 24 "text/tabwriter" 25 26 "github.com/containerd/containerd/cmd/ctr/commands" 27 "github.com/containerd/containerd/errdefs" 28 "github.com/containerd/containerd/log" 29 "github.com/pkg/errors" 30 "github.com/urfave/cli" 31 ) 32 33 // Command is the cli command for managing namespaces 34 var Command = cli.Command{ 35 Name: "namespaces", 36 Aliases: []string{"namespace", "ns"}, 37 Usage: "manage namespaces", 38 Subcommands: cli.Commands{ 39 createCommand, 40 listCommand, 41 removeCommand, 42 setLabelsCommand, 43 }, 44 } 45 46 var createCommand = cli.Command{ 47 Name: "create", 48 Aliases: []string{"c"}, 49 Usage: "create a new namespace", 50 ArgsUsage: "<name> [<key>=<value]", 51 Description: "create a new namespace. it must be unique", 52 Action: func(context *cli.Context) error { 53 namespace, labels := commands.ObjectWithLabelArgs(context) 54 if namespace == "" { 55 return errors.New("please specify a namespace") 56 } 57 client, ctx, cancel, err := commands.NewClient(context) 58 if err != nil { 59 return err 60 } 61 defer cancel() 62 namespaces := client.NamespaceService() 63 return namespaces.Create(ctx, namespace, labels) 64 }, 65 } 66 67 var setLabelsCommand = cli.Command{ 68 Name: "label", 69 Usage: "set and clear labels for a namespace", 70 ArgsUsage: "<name> [<key>=<value>, ...]", 71 Description: "set and clear labels for a namespace", 72 Action: func(context *cli.Context) error { 73 namespace, labels := commands.ObjectWithLabelArgs(context) 74 if namespace == "" { 75 return errors.New("please specify a namespace") 76 } 77 client, ctx, cancel, err := commands.NewClient(context) 78 if err != nil { 79 return err 80 } 81 defer cancel() 82 namespaces := client.NamespaceService() 83 for k, v := range labels { 84 if err := namespaces.SetLabel(ctx, namespace, k, v); err != nil { 85 return err 86 } 87 } 88 return nil 89 }, 90 } 91 92 var listCommand = cli.Command{ 93 Name: "list", 94 Aliases: []string{"ls"}, 95 Usage: "list namespaces", 96 ArgsUsage: "[flags]", 97 Description: "list namespaces", 98 Flags: []cli.Flag{ 99 cli.BoolFlag{ 100 Name: "quiet, q", 101 Usage: "print only the namespace name", 102 }, 103 }, 104 Action: func(context *cli.Context) error { 105 quiet := context.Bool("quiet") 106 client, ctx, cancel, err := commands.NewClient(context) 107 if err != nil { 108 return err 109 } 110 defer cancel() 111 namespaces := client.NamespaceService() 112 nss, err := namespaces.List(ctx) 113 if err != nil { 114 return err 115 } 116 117 if quiet { 118 for _, ns := range nss { 119 fmt.Println(ns) 120 } 121 return nil 122 } 123 124 tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0) 125 fmt.Fprintln(tw, "NAME\tLABELS\t") 126 for _, ns := range nss { 127 labels, err := namespaces.Labels(ctx, ns) 128 if err != nil { 129 return err 130 } 131 132 var labelStrings []string 133 for k, v := range labels { 134 labelStrings = append(labelStrings, strings.Join([]string{k, v}, "=")) 135 } 136 sort.Strings(labelStrings) 137 138 fmt.Fprintf(tw, "%v\t%v\t\n", ns, strings.Join(labelStrings, ",")) 139 } 140 return tw.Flush() 141 }, 142 } 143 144 var removeCommand = cli.Command{ 145 Name: "remove", 146 Aliases: []string{"rm"}, 147 Usage: "remove one or more namespaces", 148 ArgsUsage: "<name> [<name>, ...]", 149 Description: "remove one or more namespaces. for now, the namespace must be empty", 150 Flags: []cli.Flag{ 151 cli.BoolFlag{ 152 Name: "cgroup,c", 153 Usage: "delete the namespace's cgroup", 154 }, 155 }, 156 Action: func(context *cli.Context) error { 157 var exitErr error 158 client, ctx, cancel, err := commands.NewClient(context) 159 if err != nil { 160 return err 161 } 162 defer cancel() 163 164 opts := deleteOpts(context) 165 namespaces := client.NamespaceService() 166 for _, target := range context.Args() { 167 if err := namespaces.Delete(ctx, target, opts...); err != nil { 168 if !errdefs.IsNotFound(err) { 169 if exitErr == nil { 170 exitErr = errors.Wrapf(err, "unable to delete %v", target) 171 } 172 log.G(ctx).WithError(err).Errorf("unable to delete %v", target) 173 continue 174 } 175 176 } 177 178 fmt.Println(target) 179 } 180 return exitErr 181 }, 182 }