github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/cmd/ctr/commands/images/import.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 images 18 19 import ( 20 "fmt" 21 "io" 22 "os" 23 "time" 24 25 "github.com/containerd/containerd" 26 "github.com/containerd/containerd/cmd/ctr/commands" 27 "github.com/containerd/containerd/images/archive" 28 "github.com/containerd/containerd/log" 29 "github.com/urfave/cli" 30 ) 31 32 var importCommand = cli.Command{ 33 Name: "import", 34 Usage: "import images", 35 ArgsUsage: "[flags] <in>", 36 Description: `Import images from a tar stream. 37 Implemented formats: 38 - oci.v1 39 - docker.v1.1 40 - docker.v1.2 41 42 43 For OCI v1, you may need to specify --base-name because an OCI archive may 44 contain only partial image references (tags without the base image name). 45 If no base image name is provided, a name will be generated as "import-%{yyyy-MM-dd}". 46 47 e.g. 48 $ ctr images import --base-name foo/bar foobar.tar 49 50 If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadbeef", the command will create 51 "foo/bar:latest" and "foo/bar@sha256:deadbeef" images in the containerd store. 52 `, 53 Flags: append([]cli.Flag{ 54 cli.StringFlag{ 55 Name: "base-name", 56 Value: "", 57 Usage: "base image name for added images, when provided only images with this name prefix are imported", 58 }, 59 cli.BoolFlag{ 60 Name: "digests", 61 Usage: "whether to create digest images (default: false)", 62 }, 63 cli.StringFlag{ 64 Name: "index-name", 65 Usage: "image name to keep index as, by default index is discarded", 66 }, 67 cli.BoolFlag{ 68 Name: "all-platforms", 69 Usage: "imports content for all platforms, false by default", 70 }, 71 cli.BoolFlag{ 72 Name: "no-unpack", 73 Usage: "skip unpacking the images, false by default", 74 }, 75 cli.BoolFlag{ 76 Name: "compress-blobs", 77 Usage: "compress uncompressed blobs when creating manifest (Docker format only)", 78 }, 79 }, commands.SnapshotterFlags...), 80 81 Action: func(context *cli.Context) error { 82 var ( 83 in = context.Args().First() 84 opts []containerd.ImportOpt 85 ) 86 87 prefix := context.String("base-name") 88 if prefix == "" { 89 prefix = fmt.Sprintf("import-%s", time.Now().Format("2006-01-02")) 90 opts = append(opts, containerd.WithImageRefTranslator(archive.AddRefPrefix(prefix))) 91 } else { 92 // When provided, filter out references which do not match 93 opts = append(opts, containerd.WithImageRefTranslator(archive.FilterRefPrefix(prefix))) 94 } 95 96 if context.Bool("digests") { 97 opts = append(opts, containerd.WithDigestRef(archive.DigestTranslator(prefix))) 98 } 99 100 if idxName := context.String("index-name"); idxName != "" { 101 opts = append(opts, containerd.WithIndexName(idxName)) 102 } 103 104 if context.Bool("compress-blobs") { 105 opts = append(opts, containerd.WithImportCompression()) 106 } 107 108 opts = append(opts, containerd.WithAllPlatforms(context.Bool("all-platforms"))) 109 110 client, ctx, cancel, err := commands.NewClient(context) 111 if err != nil { 112 return err 113 } 114 defer cancel() 115 116 var r io.ReadCloser 117 if in == "-" { 118 r = os.Stdin 119 } else { 120 r, err = os.Open(in) 121 if err != nil { 122 return err 123 } 124 } 125 imgs, err := client.Import(ctx, r, opts...) 126 closeErr := r.Close() 127 if err != nil { 128 return err 129 } 130 if closeErr != nil { 131 return closeErr 132 } 133 134 if !context.Bool("no-unpack") { 135 log.G(ctx).Debugf("unpacking %d images", len(imgs)) 136 137 for _, img := range imgs { 138 // TODO: Allow configuration of the platform 139 image := containerd.NewImage(client, img) 140 141 // TODO: Show unpack status 142 fmt.Printf("unpacking %s (%s)...", img.Name, img.Target.Digest) 143 err = image.Unpack(ctx, context.String("snapshotter")) 144 if err != nil { 145 return err 146 } 147 fmt.Println("done") 148 } 149 } 150 return nil 151 }, 152 }