mirror of
https://github.com/containers/podman.git
synced 2025-09-25 15:55:32 +08:00
vendor c/common@main
Update the `--filter reference=...` tests to reflect recent changes in c/common. The reference values now match as specified without implicitly adding wildcards arounds. Fixes: #11905 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
56
vendor/github.com/containers/common/libimage/filters.go
generated
vendored
56
vendor/github.com/containers/common/libimage/filters.go
generated
vendored
@ -3,13 +3,14 @@ package libimage
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
filtersPkg "github.com/containers/common/pkg/filters"
|
||||
"github.com/containers/common/pkg/timetype"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -136,7 +137,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
||||
filterFuncs = append(filterFuncs, filterReadOnly(readOnly))
|
||||
|
||||
case "reference":
|
||||
filterFuncs = append(filterFuncs, filterReference(value))
|
||||
filterFuncs = append(filterFuncs, filterReferences(value))
|
||||
|
||||
case "until":
|
||||
ts, err := timetype.GetTimestamp(value, time.Now())
|
||||
@ -158,24 +159,43 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
||||
return filterFuncs, nil
|
||||
}
|
||||
|
||||
// filterReference creates a reference filter for matching the specified value.
|
||||
func filterReference(value string) filterFunc {
|
||||
// Replacing all '/' with '|' so that filepath.Match() can work '|'
|
||||
// character is not valid in image name, so this is safe.
|
||||
//
|
||||
// TODO: this has been copied from Podman and requires some more review
|
||||
// and especially tests.
|
||||
filter := fmt.Sprintf("*%s*", value)
|
||||
filter = strings.ReplaceAll(filter, "/", "|")
|
||||
// filterReferences creates a reference filter for matching the specified value.
|
||||
func filterReferences(value string) filterFunc {
|
||||
return func(img *Image) (bool, error) {
|
||||
if len(value) < 1 {
|
||||
return true, nil
|
||||
refs, err := img.NamesReferences()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, name := range img.Names() {
|
||||
newName := strings.ReplaceAll(name, "/", "|")
|
||||
match, _ := filepath.Match(filter, newName)
|
||||
if match {
|
||||
return true, nil
|
||||
|
||||
for _, ref := range refs {
|
||||
refString := ref.String() // FQN with tag/digest
|
||||
candidates := []string{refString}
|
||||
|
||||
// Split the reference into 3 components (twice if diggested/tagged):
|
||||
// 1) Fully-qualified reference
|
||||
// 2) Without domain
|
||||
// 3) Without domain and path
|
||||
if named, isNamed := ref.(reference.Named); isNamed {
|
||||
candidates = append(candidates,
|
||||
reference.Path(named), // path/name without tag/digest (Path() removes it)
|
||||
refString[strings.LastIndex(refString, "/")+1:]) // name with tag/digest
|
||||
|
||||
trimmedString := reference.TrimNamed(named).String()
|
||||
if refString != trimmedString {
|
||||
tagOrDigest := refString[len(trimmedString):]
|
||||
candidates = append(candidates,
|
||||
trimmedString, // FQN without tag/digest
|
||||
reference.Path(named)+tagOrDigest, // path/name with tag/digest
|
||||
trimmedString[strings.LastIndex(trimmedString, "/")+1:]) // name without tag/digest
|
||||
}
|
||||
}
|
||||
|
||||
for _, candidate := range candidates {
|
||||
// path.Match() is also used by Docker's reference.FamiliarMatch().
|
||||
matched, _ := path.Match(value, candidate)
|
||||
if matched {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
|
20
vendor/github.com/containers/common/libimage/image.go
generated
vendored
20
vendor/github.com/containers/common/libimage/image.go
generated
vendored
@ -44,6 +44,8 @@ type Image struct {
|
||||
completeInspectData *ImageData
|
||||
// Corresponding OCI image.
|
||||
ociv1Image *ociv1.Image
|
||||
// Names() parsed into references.
|
||||
namesReferences []reference.Reference
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +61,7 @@ func (i *Image) reload() error {
|
||||
i.cached.partialInspectData = nil
|
||||
i.cached.completeInspectData = nil
|
||||
i.cached.ociv1Image = nil
|
||||
i.cached.namesReferences = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -89,6 +92,23 @@ func (i *Image) Names() []string {
|
||||
return i.storageImage.Names
|
||||
}
|
||||
|
||||
// NamesReferences returns Names() as references.
|
||||
func (i *Image) NamesReferences() ([]reference.Reference, error) {
|
||||
if i.cached.namesReferences != nil {
|
||||
return i.cached.namesReferences, nil
|
||||
}
|
||||
refs := make([]reference.Reference, 0, len(i.Names()))
|
||||
for _, name := range i.Names() {
|
||||
ref, err := reference.Parse(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refs = append(refs, ref)
|
||||
}
|
||||
i.cached.namesReferences = refs
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
// StorageImage returns the underlying storage.Image.
|
||||
func (i *Image) StorageImage() *storage.Image {
|
||||
return i.storageImage
|
||||
|
108
vendor/github.com/containers/common/pkg/auth/auth.go
generated
vendored
108
vendor/github.com/containers/common/pkg/auth/auth.go
generated
vendored
@ -70,13 +70,10 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
|
||||
systemContext = systemContextWithOptions(systemContext, opts.AuthFile, opts.CertDir)
|
||||
|
||||
var (
|
||||
authConfig types.DockerAuthConfig
|
||||
key, registry string
|
||||
ref reference.Named
|
||||
err error
|
||||
)
|
||||
l := len(args)
|
||||
switch l {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
if !opts.AcceptUnspecifiedRegistry {
|
||||
return errors.New("please provide a registry to login to")
|
||||
@ -88,26 +85,18 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
|
||||
logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", key)
|
||||
|
||||
case 1:
|
||||
key, registry, ref, err = parseRegistryArgument(args[0], opts.AcceptRepositories)
|
||||
key, registry, err = parseCredentialsKey(args[0], opts.AcceptRepositories)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return errors.New("login accepts only one registry to login to")
|
||||
|
||||
}
|
||||
|
||||
if ref != nil {
|
||||
authConfig, err = config.GetCredentialsForRef(systemContext, ref)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials for repository")
|
||||
}
|
||||
} else {
|
||||
authConfig, err = config.GetCredentials(systemContext, registry)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials")
|
||||
}
|
||||
authConfig, err := config.GetCredentials(systemContext, key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials")
|
||||
}
|
||||
|
||||
if opts.GetLoginSet {
|
||||
@ -173,39 +162,44 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
|
||||
return errors.Wrapf(err, "authenticating creds for %q", key)
|
||||
}
|
||||
|
||||
// parseRegistryArgument verifies the provided arg depending if we accept
|
||||
// repositories or not.
|
||||
func parseRegistryArgument(arg string, acceptRepositories bool) (key, registry string, maybeRef reference.Named, err error) {
|
||||
// parseCredentialsKey turns the provided argument into a valid credential key
|
||||
// and computes the registry part.
|
||||
func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry string, err error) {
|
||||
if !acceptRepositories {
|
||||
registry = getRegistryName(arg)
|
||||
key = registry
|
||||
return key, registry, maybeRef, nil
|
||||
return key, registry, nil
|
||||
}
|
||||
|
||||
key = trimScheme(arg)
|
||||
if key != arg {
|
||||
return key, registry, nil, errors.New("credentials key has https[s]:// prefix")
|
||||
return "", "", errors.New("credentials key has https[s]:// prefix")
|
||||
}
|
||||
|
||||
registry = getRegistryName(key)
|
||||
if registry == key {
|
||||
// We cannot parse a reference from a registry, so we stop here
|
||||
return key, registry, nil, nil
|
||||
// The key is not namespaced
|
||||
return key, registry, nil
|
||||
}
|
||||
|
||||
ref, parseErr := reference.ParseNamed(key)
|
||||
if parseErr != nil {
|
||||
return key, registry, nil, errors.Wrapf(parseErr, "parse reference from %q", key)
|
||||
// Sanity-check that the key looks reasonable (e.g. doesn't use invalid characters),
|
||||
// and does not contain a tag or digest.
|
||||
// WARNING: ref.Named() MUST NOT be used to compute key, because
|
||||
// reference.ParseNormalizedNamed() turns docker.io/vendor to docker.io/library/vendor
|
||||
// Ideally c/image should provide dedicated validation functionality.
|
||||
ref, err := reference.ParseNormalizedNamed(key)
|
||||
if err != nil {
|
||||
return "", "", errors.Wrapf(err, "parse reference from %q", key)
|
||||
}
|
||||
|
||||
if !reference.IsNameOnly(ref) {
|
||||
return key, registry, nil, errors.Errorf("reference %q contains tag or digest", ref.String())
|
||||
return "", "", errors.Errorf("reference %q contains tag or digest", ref.String())
|
||||
}
|
||||
refRegistry := reference.Domain(ref)
|
||||
if refRegistry != registry { // This should never happen, check just to make sure
|
||||
return "", "", fmt.Errorf("internal error: key %q registry mismatch, %q vs. %q", key, ref, refRegistry)
|
||||
}
|
||||
|
||||
maybeRef = ref
|
||||
registry = reference.Domain(ref)
|
||||
|
||||
return key, registry, maybeRef, nil
|
||||
return key, registry, nil
|
||||
}
|
||||
|
||||
// getRegistryName scrubs and parses the input to get the server name
|
||||
@ -271,15 +265,23 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
|
||||
}
|
||||
systemContext = systemContextWithOptions(systemContext, opts.AuthFile, "")
|
||||
|
||||
if opts.All {
|
||||
if len(args) != 0 {
|
||||
return errors.New("--all takes no arguments")
|
||||
}
|
||||
if err := config.RemoveAllAuthentication(systemContext); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(opts.Stdout, "Removed login credentials for all registries")
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
key, registry string
|
||||
ref reference.Named
|
||||
err error
|
||||
)
|
||||
if len(args) > 1 {
|
||||
return errors.New("logout accepts only one registry to logout from")
|
||||
}
|
||||
if len(args) == 0 && !opts.All {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
if !opts.AcceptUnspecifiedRegistry {
|
||||
return errors.New("please provide a registry to logout from")
|
||||
}
|
||||
@ -288,23 +290,15 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
|
||||
}
|
||||
registry = key
|
||||
logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", key)
|
||||
}
|
||||
if len(args) != 0 {
|
||||
if opts.All {
|
||||
return errors.New("--all takes no arguments")
|
||||
}
|
||||
key, registry, ref, err = parseRegistryArgument(args[0], opts.AcceptRepositories)
|
||||
|
||||
case 1:
|
||||
key, registry, err = parseCredentialsKey(args[0], opts.AcceptRepositories)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.All {
|
||||
if err := config.RemoveAllAuthentication(systemContext); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(opts.Stdout, "Removed login credentials for all registries")
|
||||
return nil
|
||||
default:
|
||||
return errors.New("logout accepts only one registry to logout from")
|
||||
}
|
||||
|
||||
err = config.RemoveAuthentication(systemContext, key)
|
||||
@ -313,17 +307,9 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
|
||||
fmt.Fprintf(opts.Stdout, "Removed login credentials for %s\n", key)
|
||||
return nil
|
||||
case config.ErrNotLoggedIn:
|
||||
var authConfig types.DockerAuthConfig
|
||||
if ref != nil {
|
||||
authConfig, err = config.GetCredentialsForRef(systemContext, ref)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials for repository")
|
||||
}
|
||||
} else {
|
||||
authConfig, err = config.GetCredentials(systemContext, registry)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials")
|
||||
}
|
||||
authConfig, err := config.GetCredentials(systemContext, key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials")
|
||||
}
|
||||
|
||||
authInvalid := docker.CheckAuth(context.Background(), systemContext, authConfig.Username, authConfig.Password, registry)
|
||||
|
11
vendor/github.com/containers/common/pkg/retry/retry.go
generated
vendored
11
vendor/github.com/containers/common/pkg/retry/retry.go
generated
vendored
@ -45,8 +45,12 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
|
||||
func isRetryable(err error) bool {
|
||||
err = errors.Cause(err)
|
||||
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
switch err {
|
||||
case nil:
|
||||
return false
|
||||
case context.Canceled, context.DeadlineExceeded:
|
||||
return false
|
||||
default: // continue
|
||||
}
|
||||
|
||||
type unwrapper interface {
|
||||
@ -57,7 +61,8 @@ func isRetryable(err error) bool {
|
||||
|
||||
case errcode.Error:
|
||||
switch e.Code {
|
||||
case errcode.ErrorCodeUnauthorized, errcodev2.ErrorCodeNameUnknown, errcodev2.ErrorCodeManifestUnknown:
|
||||
case errcode.ErrorCodeUnauthorized, errcode.ErrorCodeDenied,
|
||||
errcodev2.ErrorCodeNameUnknown, errcodev2.ErrorCodeManifestUnknown:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -86,7 +91,7 @@ func isRetryable(err error) bool {
|
||||
}
|
||||
}
|
||||
return true
|
||||
case unwrapper:
|
||||
case unwrapper: // Test this last, because various error types might implement .Unwrap()
|
||||
err = e.Unwrap()
|
||||
return isRetryable(err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user