github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/image_convert.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 main 18 19 import ( 20 "compress/gzip" 21 22 "github.com/containerd/nerdctl/pkg/api/types" 23 "github.com/containerd/nerdctl/pkg/clientutil" 24 "github.com/containerd/nerdctl/pkg/cmd/image" 25 "github.com/spf13/cobra" 26 ) 27 28 const imageConvertHelp = `Convert an image format. 29 30 e.g., 'nerdctl image convert --estargz --oci example.com/foo:orig example.com/foo:esgz' 31 32 Use '--platform' to define the output platform. 33 When '--all-platforms' is given all images in a manifest list must be available. 34 35 For encryption and decryption, use 'nerdctl image (encrypt|decrypt)' command. 36 ` 37 38 // imageConvertCommand is from https://github.com/containerd/stargz-snapshotter/blob/d58f43a8235e46da73fb94a1a35280cb4d607b2c/cmd/ctr-remote/commands/convert.go 39 func newImageConvertCommand() *cobra.Command { 40 imageConvertCommand := &cobra.Command{ 41 Use: "convert [flags] <source_ref> <target_ref>...", 42 Short: "convert an image", 43 Long: imageConvertHelp, 44 Args: cobra.MinimumNArgs(2), 45 RunE: imageConvertAction, 46 ValidArgsFunction: imageConvertShellComplete, 47 SilenceUsage: true, 48 SilenceErrors: true, 49 } 50 51 imageConvertCommand.Flags().String("format", "", "Format the output using the given Go template, e.g, 'json'") 52 53 // #region estargz flags 54 imageConvertCommand.Flags().Bool("estargz", false, "Convert legacy tar(.gz) layers to eStargz for lazy pulling. Should be used in conjunction with '--oci'") 55 imageConvertCommand.Flags().String("estargz-record-in", "", "Read 'ctr-remote optimize --record-out=<FILE>' record file (EXPERIMENTAL)") 56 imageConvertCommand.Flags().Int("estargz-compression-level", gzip.BestCompression, "eStargz compression level") 57 imageConvertCommand.Flags().Int("estargz-chunk-size", 0, "eStargz chunk size") 58 imageConvertCommand.Flags().Int("estargz-min-chunk-size", 0, "The minimal number of bytes of data must be written in one gzip stream. (requires stargz-snapshotter >= v0.13.0)") 59 imageConvertCommand.Flags().Bool("estargz-external-toc", false, "Separate TOC JSON into another image (called \"TOC image\"). The name of TOC image is the original + \"-esgztoc\" suffix. Both eStargz and the TOC image should be pushed to the same registry. (requires stargz-snapshotter >= v0.13.0) (EXPERIMENTAL)") 60 imageConvertCommand.Flags().Bool("estargz-keep-diff-id", false, "Convert to esgz without changing diffID (cannot be used in conjunction with '--estargz-record-in'. must be specified with '--estargz-external-toc')") 61 // #endregion 62 63 // #region zstd flags 64 imageConvertCommand.Flags().Bool("zstd", false, "Convert legacy tar(.gz) layers to zstd. Should be used in conjunction with '--oci'") 65 imageConvertCommand.Flags().Int("zstd-compression-level", 3, "zstd compression level") 66 // #endregion 67 68 // #region zstd:chunked flags 69 imageConvertCommand.Flags().Bool("zstdchunked", false, "Convert legacy tar(.gz) layers to zstd:chunked for lazy pulling. Should be used in conjunction with '--oci'") 70 imageConvertCommand.Flags().String("zstdchunked-record-in", "", "Read 'ctr-remote optimize --record-out=<FILE>' record file (EXPERIMENTAL)") 71 imageConvertCommand.Flags().Int("zstdchunked-compression-level", 3, "zstd:chunked compression level") // SpeedDefault; see also https://pkg.go.dev/github.com/klauspost/compress/zstd#EncoderLevel 72 imageConvertCommand.Flags().Int("zstdchunked-chunk-size", 0, "zstd:chunked chunk size") 73 // #endregion 74 75 // #region nydus flags 76 imageConvertCommand.Flags().Bool("nydus", false, "Convert an OCI image to Nydus image. Should be used in conjunction with '--oci'") 77 imageConvertCommand.Flags().String("nydus-builder-path", "nydus-image", "The nydus-image binary path, if unset, search in PATH environment") 78 imageConvertCommand.Flags().String("nydus-work-dir", "", "Work directory path for image conversion, default is the nerdctl data root directory") 79 imageConvertCommand.Flags().String("nydus-prefetch-patterns", "", "The file path pattern list want to prefetch") 80 imageConvertCommand.Flags().String("nydus-compressor", "lz4_block", "Nydus blob compression algorithm, possible values: `none`, `lz4_block`, `zstd`, default is `lz4_block`") 81 // #endregion 82 83 // #region overlaybd flags 84 imageConvertCommand.Flags().Bool("overlaybd", false, "Convert tar.gz layers to overlaybd layers") 85 imageConvertCommand.Flags().String("overlaybd-fs-type", "ext4", "Filesystem type for overlaybd") 86 imageConvertCommand.Flags().String("overlaybd-dbstr", "", "Database config string for overlaybd") 87 // #endregion 88 89 // #region generic flags 90 imageConvertCommand.Flags().Bool("uncompress", false, "Convert tar.gz layers to uncompressed tar layers") 91 imageConvertCommand.Flags().Bool("oci", false, "Convert Docker media types to OCI media types") 92 // #endregion 93 94 // #region platform flags 95 // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" 96 imageConvertCommand.Flags().StringSlice("platform", []string{}, "Convert content for a specific platform") 97 imageConvertCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) 98 imageConvertCommand.Flags().Bool("all-platforms", false, "Convert content for all platforms") 99 // #endregion 100 101 return imageConvertCommand 102 } 103 104 func processImageConvertOptions(cmd *cobra.Command) (types.ImageConvertOptions, error) { 105 globalOptions, err := processRootCmdFlags(cmd) 106 if err != nil { 107 return types.ImageConvertOptions{}, err 108 } 109 format, err := cmd.Flags().GetString("format") 110 if err != nil { 111 return types.ImageConvertOptions{}, err 112 } 113 114 // #region estargz flags 115 estargz, err := cmd.Flags().GetBool("estargz") 116 if err != nil { 117 return types.ImageConvertOptions{}, err 118 } 119 estargzRecordIn, err := cmd.Flags().GetString("estargz-record-in") 120 if err != nil { 121 return types.ImageConvertOptions{}, err 122 } 123 estargzCompressionLevel, err := cmd.Flags().GetInt("estargz-compression-level") 124 if err != nil { 125 return types.ImageConvertOptions{}, err 126 } 127 estargzChunkSize, err := cmd.Flags().GetInt("estargz-chunk-size") 128 if err != nil { 129 return types.ImageConvertOptions{}, err 130 } 131 estargzMinChunkSize, err := cmd.Flags().GetInt("estargz-min-chunk-size") 132 if err != nil { 133 return types.ImageConvertOptions{}, err 134 } 135 estargzExternalTOC, err := cmd.Flags().GetBool("estargz-external-toc") 136 if err != nil { 137 return types.ImageConvertOptions{}, err 138 } 139 estargzKeepDiffID, err := cmd.Flags().GetBool("estargz-keep-diff-id") 140 if err != nil { 141 return types.ImageConvertOptions{}, err 142 } 143 // #endregion 144 145 // #region zstd flags 146 zstd, err := cmd.Flags().GetBool("zstd") 147 if err != nil { 148 return types.ImageConvertOptions{}, err 149 } 150 zstdCompressionLevel, err := cmd.Flags().GetInt("zstd-compression-level") 151 if err != nil { 152 return types.ImageConvertOptions{}, err 153 } 154 // #endregion 155 156 // #region zstd:chunked flags 157 zstdchunked, err := cmd.Flags().GetBool("zstdchunked") 158 if err != nil { 159 return types.ImageConvertOptions{}, err 160 } 161 zstdChunkedCompressionLevel, err := cmd.Flags().GetInt("zstdchunked-compression-level") 162 if err != nil { 163 return types.ImageConvertOptions{}, err 164 } 165 zstdChunkedChunkSize, err := cmd.Flags().GetInt("zstdchunked-chunk-size") 166 if err != nil { 167 return types.ImageConvertOptions{}, err 168 } 169 zstdChunkedRecordIn, err := cmd.Flags().GetString("zstdchunked-record-in") 170 if err != nil { 171 return types.ImageConvertOptions{}, err 172 } 173 // #endregion 174 175 // #region nydus flags 176 nydus, err := cmd.Flags().GetBool("nydus") 177 if err != nil { 178 return types.ImageConvertOptions{}, err 179 } 180 nydusBuilderPath, err := cmd.Flags().GetString("nydus-builder-path") 181 if err != nil { 182 return types.ImageConvertOptions{}, err 183 } 184 nydusWorkDir, err := cmd.Flags().GetString("nydus-work-dir") 185 if err != nil { 186 return types.ImageConvertOptions{}, err 187 } 188 nydusPrefetchPatterns, err := cmd.Flags().GetString("nydus-prefetch-patterns") 189 if err != nil { 190 return types.ImageConvertOptions{}, err 191 } 192 nydusCompressor, err := cmd.Flags().GetString("nydus-compressor") 193 if err != nil { 194 return types.ImageConvertOptions{}, err 195 } 196 // #endregion 197 198 // #region overlaybd flags 199 overlaybd, err := cmd.Flags().GetBool("overlaybd") 200 if err != nil { 201 return types.ImageConvertOptions{}, err 202 } 203 overlaybdFsType, err := cmd.Flags().GetString("overlaybd-fs-type") 204 if err != nil { 205 return types.ImageConvertOptions{}, err 206 } 207 overlaybdDbstr, err := cmd.Flags().GetString("overlaybd-dbstr") 208 if err != nil { 209 return types.ImageConvertOptions{}, err 210 } 211 // #endregion 212 213 // #region generic flags 214 uncompress, err := cmd.Flags().GetBool("uncompress") 215 if err != nil { 216 return types.ImageConvertOptions{}, err 217 } 218 oci, err := cmd.Flags().GetBool("oci") 219 if err != nil { 220 return types.ImageConvertOptions{}, err 221 } 222 // #endregion 223 224 // #region platform flags 225 platforms, err := cmd.Flags().GetStringSlice("platform") 226 if err != nil { 227 return types.ImageConvertOptions{}, err 228 } 229 allPlatforms, err := cmd.Flags().GetBool("all-platforms") 230 if err != nil { 231 return types.ImageConvertOptions{}, err 232 } 233 // #endregion 234 return types.ImageConvertOptions{ 235 GOptions: globalOptions, 236 Format: format, 237 // #region estargz flags 238 Estargz: estargz, 239 EstargzRecordIn: estargzRecordIn, 240 EstargzCompressionLevel: estargzCompressionLevel, 241 EstargzChunkSize: estargzChunkSize, 242 EstargzMinChunkSize: estargzMinChunkSize, 243 EstargzExternalToc: estargzExternalTOC, 244 EstargzKeepDiffID: estargzKeepDiffID, 245 // #endregion 246 // #region zstd flags 247 Zstd: zstd, 248 ZstdCompressionLevel: zstdCompressionLevel, 249 // #endregion 250 // #region zstd:chunked flags 251 ZstdChunked: zstdchunked, 252 ZstdChunkedCompressionLevel: zstdChunkedCompressionLevel, 253 ZstdChunkedChunkSize: zstdChunkedChunkSize, 254 ZstdChunkedRecordIn: zstdChunkedRecordIn, 255 // #endregion 256 // #region nydus flags 257 Nydus: nydus, 258 NydusBuilderPath: nydusBuilderPath, 259 NydusWorkDir: nydusWorkDir, 260 NydusPrefetchPatterns: nydusPrefetchPatterns, 261 NydusCompressor: nydusCompressor, 262 // #endregion 263 // #region overlaybd flags 264 Overlaybd: overlaybd, 265 OverlayFsType: overlaybdFsType, 266 OverlaydbDBStr: overlaybdDbstr, 267 // #endregion 268 // #region generic flags 269 Uncompress: uncompress, 270 Oci: oci, 271 // #endregion 272 // #region platform flags 273 Platforms: platforms, 274 AllPlatforms: allPlatforms, 275 // #endregion 276 Stdout: cmd.OutOrStdout(), 277 }, nil 278 } 279 280 func imageConvertAction(cmd *cobra.Command, args []string) error { 281 options, err := processImageConvertOptions(cmd) 282 if err != nil { 283 return err 284 } 285 srcRawRef := args[0] 286 destRawRef := args[1] 287 288 client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) 289 if err != nil { 290 return err 291 } 292 defer cancel() 293 294 return image.Convert(ctx, client, srcRawRef, destRawRef, options) 295 } 296 297 func imageConvertShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 298 // show image names 299 return shellCompleteImageNames(cmd) 300 }