Add authfile flag to pull and push
Push and pull can now access any cached registry credentials from the auth file Signed-off-by: umohnani8 <umohnani@redhat.com>
This commit is contained in:
parent
0914a7a667
commit
d855e2c8ad
13 changed files with 428 additions and 210 deletions
|
@ -95,14 +95,19 @@ func loadCmd(c *cli.Context) error {
|
|||
output = os.Stdout
|
||||
}
|
||||
|
||||
options := libpod.CopyOptions{
|
||||
SignaturePolicyPath: c.String("signature-policy"),
|
||||
Writer: output,
|
||||
}
|
||||
|
||||
src := libpod.DockerArchive + ":" + input
|
||||
if err := runtime.PullImage(src, false, c.String("signature-policy"), output); err != nil {
|
||||
if err := runtime.PullImage(src, options); err != nil {
|
||||
src = libpod.OCIArchive + ":" + input
|
||||
// generate full src name with specified image:tag
|
||||
if image != "" {
|
||||
src = src + ":" + image
|
||||
}
|
||||
if err := runtime.PullImage(src, false, "", output); err != nil {
|
||||
if err := runtime.PullImage(src, options); err != nil {
|
||||
return errors.Wrapf(err, "error pulling %q", src)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ func logoutCmd(c *cli.Context) error {
|
|||
if len(args) > 1 {
|
||||
return errors.Errorf("too many arguments, logout takes only 1 argument")
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("registry must be given")
|
||||
}
|
||||
var server string
|
||||
if len(args) == 1 {
|
||||
server = args[0]
|
||||
|
|
152
cmd/kpod/pull.go
152
cmd/kpod/pull.go
|
@ -1,14 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"fmt"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/pkg/sysregistries"
|
||||
"github.com/containers/image/transports/alltransports"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/kubernetes-incubator/cri-o/libpod"
|
||||
"github.com/kubernetes-incubator/cri-o/libpod/common"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
|
@ -16,16 +16,18 @@ import (
|
|||
|
||||
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",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`pathname` of signature policy file (not usually used)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "creds",
|
||||
Usage: "`credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
|
||||
},
|
||||
}
|
||||
|
||||
pullDescription = "Pulls an image from a registry and stores it locally.\n" +
|
||||
|
@ -41,83 +43,14 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// struct for when a user passes a short or incomplete
|
||||
// image name
|
||||
type imagePullStruct struct {
|
||||
imageName string
|
||||
tag string
|
||||
registry string
|
||||
hasRegistry bool
|
||||
transport string
|
||||
}
|
||||
|
||||
func (ips imagePullStruct) returnFQName() string {
|
||||
return fmt.Sprintf("%s%s/%s:%s", ips.transport, ips.registry, ips.imageName, ips.tag)
|
||||
}
|
||||
|
||||
func getRegistriesToTry(image string) ([]string, error) {
|
||||
var registries []string
|
||||
var imageError = fmt.Sprintf("unable to parse '%s'\n", image)
|
||||
imgRef, err := reference.Parse(image)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, imageError)
|
||||
}
|
||||
tagged, isTagged := imgRef.(reference.NamedTagged)
|
||||
tag := "latest"
|
||||
if isTagged {
|
||||
tag = tagged.Tag()
|
||||
}
|
||||
hasDomain := true
|
||||
registry := reference.Domain(imgRef.(reference.Named))
|
||||
if registry == "" {
|
||||
hasDomain = false
|
||||
}
|
||||
imageName := reference.Path(imgRef.(reference.Named))
|
||||
pImage := imagePullStruct{
|
||||
imageName,
|
||||
tag,
|
||||
registry,
|
||||
hasDomain,
|
||||
"docker://",
|
||||
}
|
||||
if pImage.hasRegistry {
|
||||
// If input has a registry, we have to assume they included an image
|
||||
// name but maybe not a tag
|
||||
pullRef, err := alltransports.ParseImageName(pImage.returnFQName())
|
||||
if err != nil {
|
||||
return nil, errors.Errorf(imageError)
|
||||
}
|
||||
registries = append(registries, pullRef.DockerReference().String())
|
||||
} else {
|
||||
// No registry means we check the globals registries configuration file
|
||||
// and assemble a list of candidate sources to try
|
||||
registryConfigPath := ""
|
||||
envOverride := os.Getenv("REGISTRIES_CONFIG_PATH")
|
||||
if len(envOverride) > 0 {
|
||||
registryConfigPath = envOverride
|
||||
}
|
||||
searchRegistries, err := sysregistries.GetRegistries(&types.SystemContext{SystemRegistriesConfPath: registryConfigPath})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, errors.Errorf("unable to parse the registries.conf file and"+
|
||||
" the image name '%s' is incomplete.", imageName)
|
||||
}
|
||||
for _, searchRegistry := range searchRegistries {
|
||||
pImage.registry = searchRegistry
|
||||
pullRef, err := alltransports.ParseImageName(pImage.returnFQName())
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("unable to parse '%s'", pImage.returnFQName())
|
||||
}
|
||||
registries = append(registries, pullRef.DockerReference().String())
|
||||
}
|
||||
}
|
||||
return registries, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var fqRegistries []string
|
||||
runtime, err := getRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
if len(args) == 0 {
|
||||
|
@ -132,31 +65,34 @@ func pullCmd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
image := args[0]
|
||||
srcRef, err := alltransports.ParseImageName(image)
|
||||
if err != nil {
|
||||
fqRegistries, err = getRegistriesToTry(image)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fqRegistries = append(fqRegistries, srcRef.DockerReference().String())
|
||||
}
|
||||
runtime, err := getRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
for _, fqname := range fqRegistries {
|
||||
fmt.Printf("Trying to pull %s...", fqname)
|
||||
if err := runtime.PullImage(fqname, c.Bool("all-tags"), c.String("signature-policy"), os.Stdout); err != nil {
|
||||
fmt.Printf(" Failed\n")
|
||||
} else {
|
||||
return nil
|
||||
var registryCreds *types.DockerAuthConfig
|
||||
if c.String("creds") != "" {
|
||||
creds, err := common.ParseRegistryCreds(c.String("creds"))
|
||||
if err != nil {
|
||||
if err == common.ErrNoPassword {
|
||||
fmt.Print("Password: ")
|
||||
password, err := terminal.ReadPassword(0)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not read password from terminal")
|
||||
}
|
||||
creds.Password = string(password)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
registryCreds = creds
|
||||
}
|
||||
return errors.Errorf("error pulling image from %q", image)
|
||||
|
||||
options := libpod.CopyOptions{
|
||||
SignaturePolicyPath: c.String("signature-policy"),
|
||||
AuthFile: c.String("authfile"),
|
||||
DockerRegistryOptions: common.DockerRegistryOptions{
|
||||
DockerRegistryCreds: registryCreds,
|
||||
},
|
||||
Writer: os.Stdout,
|
||||
}
|
||||
|
||||
return runtime.PullImage(image, options)
|
||||
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@ var (
|
|||
Name: "quiet, q",
|
||||
Usage: "don't output progress information when pushing images",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json",
|
||||
},
|
||||
}
|
||||
pushDescription = fmt.Sprintf(`
|
||||
Pushes an image to a specified location.
|
||||
|
@ -120,7 +124,9 @@ func pushCmd(c *cli.Context) error {
|
|||
RemoveSignatures: removeSignatures,
|
||||
SignBy: signBy,
|
||||
},
|
||||
AuthFile: c.String("authfile"),
|
||||
Writer: writer,
|
||||
}
|
||||
|
||||
return runtime.PushImage(srcName, destName, options, writer)
|
||||
return runtime.PushImage(srcName, destName, options)
|
||||
}
|
||||
|
|
|
@ -83,13 +83,14 @@ func saveCmd(c *cli.Context) error {
|
|||
|
||||
saveOpts := libpod.CopyOptions{
|
||||
SignaturePolicyPath: "",
|
||||
Writer: writer,
|
||||
}
|
||||
|
||||
// only one image is supported for now
|
||||
// future pull requests will fix this
|
||||
for _, image := range args {
|
||||
dest := dst + ":" + image
|
||||
if err := runtime.PushImage(image, dest, saveOpts, writer); err != nil {
|
||||
if err := runtime.PushImage(image, dest, saveOpts); err != nil {
|
||||
return errors.Wrapf(err, "unable to save %q", image)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue