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  }