github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/cmd/ctr/commands/images/pull.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  
    22  	"github.com/containerd/containerd"
    23  	"github.com/containerd/containerd/cmd/ctr/commands"
    24  	"github.com/containerd/containerd/cmd/ctr/commands/content"
    25  	"github.com/containerd/containerd/images"
    26  	"github.com/containerd/containerd/log"
    27  	"github.com/containerd/containerd/platforms"
    28  	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
    29  	"github.com/pkg/errors"
    30  	"github.com/urfave/cli"
    31  )
    32  
    33  var pullCommand = cli.Command{
    34  	Name:      "pull",
    35  	Usage:     "pull an image from a remote",
    36  	ArgsUsage: "[flags] <ref>",
    37  	Description: `Fetch and prepare an image for use in containerd.
    38  
    39  After pulling an image, it should be ready to use the same reference in a run
    40  command. As part of this process, we do the following:
    41  
    42  1. Fetch all resources into containerd.
    43  2. Prepare the snapshot filesystem with the pulled resources.
    44  3. Register metadata for the image.
    45  `,
    46  	Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...),
    47  		cli.StringSliceFlag{
    48  			Name:  "platform",
    49  			Usage: "Pull content from a specific platform",
    50  			Value: &cli.StringSlice{},
    51  		},
    52  		cli.BoolFlag{
    53  			Name:  "all-platforms",
    54  			Usage: "pull content and metadata from all platforms",
    55  		},
    56  		cli.BoolFlag{
    57  			Name:  "all-metadata",
    58  			Usage: "Pull metadata for all platforms",
    59  		},
    60  	),
    61  	Action: func(context *cli.Context) error {
    62  		var (
    63  			ref = context.Args().First()
    64  		)
    65  		if ref == "" {
    66  			return fmt.Errorf("please provide an image reference to pull")
    67  		}
    68  
    69  		client, ctx, cancel, err := commands.NewClient(context)
    70  		if err != nil {
    71  			return err
    72  		}
    73  		defer cancel()
    74  
    75  		ctx, done, err := client.WithLease(ctx)
    76  		if err != nil {
    77  			return err
    78  		}
    79  		defer done(ctx)
    80  
    81  		config, err := content.NewFetchConfig(ctx, context)
    82  		if err != nil {
    83  			return err
    84  		}
    85  
    86  		img, err := content.Fetch(ctx, client, ref, config)
    87  		if err != nil {
    88  			return err
    89  		}
    90  
    91  		log.G(ctx).WithField("image", ref).Debug("unpacking")
    92  
    93  		// TODO: Show unpack status
    94  
    95  		var p []ocispec.Platform
    96  		if context.Bool("all-platforms") {
    97  			p, err = images.Platforms(ctx, client.ContentStore(), img.Target)
    98  			if err != nil {
    99  				return errors.Wrap(err, "unable to resolve image platforms")
   100  			}
   101  		} else {
   102  			for _, s := range context.StringSlice("platform") {
   103  				ps, err := platforms.Parse(s)
   104  				if err != nil {
   105  					return errors.Wrapf(err, "unable to parse platform %s", s)
   106  				}
   107  				p = append(p, ps)
   108  			}
   109  		}
   110  		if len(p) == 0 {
   111  			p = append(p, platforms.DefaultSpec())
   112  		}
   113  
   114  		for _, platform := range p {
   115  			fmt.Printf("unpacking %s %s...\n", platforms.Format(platform), img.Target.Digest)
   116  			i := containerd.NewImageWithPlatform(client, img, platforms.Only(platform))
   117  			err = i.Unpack(ctx, context.String("snapshotter"))
   118  			if err != nil {
   119  				return err
   120  			}
   121  		}
   122  
   123  		fmt.Println("done")
   124  		return nil
   125  	},
   126  }