126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
|
||
|
"github.com/Sirupsen/logrus"
|
||
|
cp "github.com/containers/image/copy"
|
||
|
"github.com/containers/image/docker/reference"
|
||
|
"github.com/containers/image/signature"
|
||
|
is "github.com/containers/image/storage"
|
||
|
"github.com/containers/image/transports/alltransports"
|
||
|
"github.com/containers/image/types"
|
||
|
"github.com/containers/storage"
|
||
|
"github.com/pkg/errors"
|
||
|
"github.com/urfave/cli"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// DefaultRegistry is a prefix that we apply to an image name
|
||
|
// to check docker hub first for the image
|
||
|
DefaultRegistry = "docker://"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
pullFlags = []cli.Flag{
|
||
|
cli.BoolFlag{
|
||
|
// all-tags is hidden since it has not been implemented yet
|
||
|
Name: "all-tags, a",
|
||
|
Hidden: true,
|
||
|
Usage: "Download all tagged images in the repository",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
pullDescription = "Pulls an image from a registry and stores it locally.\n" +
|
||
|
"An image can be pulled using its tag or digest. If a tag is not\n" +
|
||
|
"specified, the image with the 'latest' tag (if it exists) is pulled."
|
||
|
pullCommand = cli.Command{
|
||
|
Name: "pull",
|
||
|
Usage: "pull an image from a registry",
|
||
|
Description: pullDescription,
|
||
|
Flags: pullFlags,
|
||
|
Action: pullCmd,
|
||
|
ArgsUsage: "",
|
||
|
}
|
||
|
)
|
||
|
|
||
|
// pullCmd gets the data from the command line and calls pullImage
|
||
|
// to copy an image from a registry to a local machine
|
||
|
func pullCmd(c *cli.Context) error {
|
||
|
args := c.Args()
|
||
|
if len(args) == 0 {
|
||
|
logrus.Errorf("an image name must be specified")
|
||
|
return nil
|
||
|
}
|
||
|
if len(args) > 1 {
|
||
|
logrus.Errorf("too many arguments. Requires exactly 1")
|
||
|
return nil
|
||
|
}
|
||
|
image := args[0]
|
||
|
|
||
|
store, err := getStore(c)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
allTags := false
|
||
|
if c.IsSet("all-tags") {
|
||
|
allTags = c.Bool("all-tags")
|
||
|
}
|
||
|
|
||
|
systemContext := getSystemContext("")
|
||
|
|
||
|
err = pullImage(store, image, allTags, systemContext)
|
||
|
if err != nil {
|
||
|
return errors.Errorf("error pulling image from %q: %v", image, err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// pullImage copies the image from the source to the destination
|
||
|
func pullImage(store storage.Store, imgName string, allTags bool, sc *types.SystemContext) error {
|
||
|
defaultName := DefaultRegistry + imgName
|
||
|
var fromName string
|
||
|
var tag string
|
||
|
|
||
|
srcRef, err := alltransports.ParseImageName(defaultName)
|
||
|
if err != nil {
|
||
|
srcRef2, err2 := alltransports.ParseImageName(imgName)
|
||
|
if err2 != nil {
|
||
|
return errors.Wrapf(err2, "error parsing image name %q", imgName)
|
||
|
}
|
||
|
srcRef = srcRef2
|
||
|
}
|
||
|
|
||
|
ref := srcRef.DockerReference()
|
||
|
if ref != nil {
|
||
|
imgName = srcRef.DockerReference().Name()
|
||
|
fromName = imgName
|
||
|
tagged, ok := srcRef.DockerReference().(reference.NamedTagged)
|
||
|
if ok {
|
||
|
imgName = imgName + ":" + tagged.Tag()
|
||
|
tag = tagged.Tag()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
destRef, err := is.Transport.ParseStoreReference(store, imgName)
|
||
|
if err != nil {
|
||
|
return errors.Wrapf(err, "error parsing full image name %q", imgName)
|
||
|
}
|
||
|
|
||
|
policy, err := signature.DefaultPolicy(sc)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
policyContext, err := signature.NewPolicyContext(policy)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
fmt.Println(tag + ": pulling from " + fromName)
|
||
|
|
||
|
return cp.Image(policyContext, destRef, srcRef, getCopyOptions(os.Stdout))
|
||
|
}
|