pull: special case all-tags semantics

Supporting the all-tags semantics added some non-trivial code to the
pull command which does not make use of `registries.conf` and introduced
some regressions such as not adhering to the configured search registries.

Speacial case the all-tags flags to let existing users of all-tags
continue working while others can work again.  This implies that the
all-tags pull does not adhere to configured search registries while the
default (non-all-tags) pull does.

Note that this is a purely symptomaic fix.  A final solution should
include Buildah and the c/image library to avoid redundant and
error-prone code across the projects.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1701922
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg 2019-04-24 12:45:36 +02:00
parent b4cba6090d
commit b90a5107e9
2 changed files with 76 additions and 55 deletions

View File

@ -46,7 +46,7 @@ func init() {
pullCommand.SetHelpTemplate(HelpTemplate()) pullCommand.SetHelpTemplate(HelpTemplate())
pullCommand.SetUsageTemplate(UsageTemplate()) pullCommand.SetUsageTemplate(UsageTemplate())
flags := pullCommand.Flags() flags := pullCommand.Flags()
flags.BoolVar(&pullCommand.AllTags, "all-tags", false, "All tagged images inthe repository will be pulled") flags.BoolVar(&pullCommand.AllTags, "all-tags", false, "All tagged images in the repository will be pulled")
flags.StringVar(&pullCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") flags.StringVar(&pullCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.StringVar(&pullCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") flags.StringVar(&pullCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.BoolVarP(&pullCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images") flags.BoolVarP(&pullCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
@ -94,8 +94,9 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
return errors.Errorf("tag can't be used with --all-tags") return errors.Errorf("tag can't be used with --all-tags")
} }
} }
ctx := getContext() ctx := getContext()
img := args[0] imgArg := args[0]
var registryCreds *types.DockerAuthConfig var registryCreds *types.DockerAuthConfig
@ -122,20 +123,41 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify) dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
// Possible for docker-archive to have multiple tags, so use LoadFromArchiveReference instead // Special-case for docker-archive which allows multiple tags.
if strings.HasPrefix(img, dockerarchive.Transport.Name()+":") { if strings.HasPrefix(imgArg, dockerarchive.Transport.Name()+":") {
srcRef, err := alltransports.ParseImageName(img) srcRef, err := alltransports.ParseImageName(imgArg)
if err != nil { if err != nil {
return errors.Wrapf(err, "error parsing %q", img) return errors.Wrapf(err, "error parsing %q", imgArg)
} }
newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer) newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer)
if err != nil { if err != nil {
return errors.Wrapf(err, "error pulling image from %q", img) return errors.Wrapf(err, "error pulling image from %q", imgArg)
} }
fmt.Println(newImage[0].ID()) fmt.Println(newImage[0].ID())
} else {
return nil
}
authfile := getAuthFile(c.String("authfile")) authfile := getAuthFile(c.String("authfile"))
spec := img
// FIXME: the default pull consults the registries.conf's search registries
// while the all-tags pull does not. This behavior must be fixed in the
// future and span across c/buildah, c/image and c/libpod to avoid redundant
// and error prone code.
//
// See https://bugzilla.redhat.com/show_bug.cgi?id=1701922 for background
// information.
if !c.Bool("all-tags") {
newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil)
if err != nil {
return errors.Wrapf(err, "error pulling image %q", imgArg)
}
fmt.Println(newImage.ID())
return nil
}
// FIXME: all-tags should use the libpod backend instead of baking its own bread.
spec := imgArg
systemContext := image.GetSystemContext("", authfile, false) systemContext := image.GetSystemContext("", authfile, false)
srcRef, err := alltransports.ParseImageName(spec) srcRef, err := alltransports.ParseImageName(spec)
if err != nil { if err != nil {
@ -144,12 +166,11 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
spec = dockerTransport + spec spec = dockerTransport + spec
srcRef2, err2 := alltransports.ParseImageName(spec) srcRef2, err2 := alltransports.ParseImageName(spec)
if err2 != nil { if err2 != nil {
return errors.Wrapf(err2, "error parsing image name %q", img) return errors.Wrapf(err2, "error parsing image name %q", imgArg)
} }
srcRef = srcRef2 srcRef = srcRef2
} }
var names []string var names []string
if c.Bool("all-tags") {
if srcRef.DockerReference() == nil { if srcRef.DockerReference() == nil {
return errors.New("Non-docker transport is currently not supported") return errors.New("Non-docker transport is currently not supported")
} }
@ -161,9 +182,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
name := spec + ":" + tag name := spec + ":" + tag
names = append(names, name) names = append(names, name)
} }
} else {
names = append(names, spec)
}
var foundIDs []string var foundIDs []string
foundImage := true foundImage := true
for _, name := range names { for _, name := range names {
@ -176,7 +195,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
foundIDs = append(foundIDs, newImage.ID()) foundIDs = append(foundIDs, newImage.ID())
} }
if len(names) == 1 && !foundImage { if len(names) == 1 && !foundImage {
return errors.Wrapf(err, "error pulling image %q", img) return errors.Wrapf(err, "error pulling image %q", imgArg)
} }
if len(names) > 1 { if len(names) > 1 {
fmt.Println("Pulled Images:") fmt.Println("Pulled Images:")
@ -184,6 +203,6 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
for _, id := range foundIDs { for _, id := range foundIDs {
fmt.Println(id) fmt.Println(id)
} }
} // end else if strings.HasPrefix(img, dockerarchive.Transport.Name()+":")
return nil return nil
} }

View File

@ -49,6 +49,8 @@ Image stored in local container/storage
All tagged images in the repository will be pulled. All tagged images in the repository will be pulled.
Note: When using the all-tags flag, Podman will not iterate over the search registries in the containers-registries.conf(5) but will always use docker.io for unqualified image names.
**--authfile** **--authfile**
Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.