mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Remove more of registry v1 code.
Signed-off-by: Tibor Vass <tibor@docker.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
4a054ec00f
commit
7a50fe8a52
16 changed files with 43 additions and 199 deletions
|
@ -11,5 +11,5 @@ import (
|
|||
// Backend is all the methods that need to be implemented
|
||||
// to provide image specific functionality.
|
||||
type Backend interface {
|
||||
GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, bool, error)
|
||||
GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, error)
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
|
|||
return errdefs.InvalidParameter(errors.Errorf("unknown image reference format: %s", image))
|
||||
}
|
||||
|
||||
distrepo, _, err := s.backend.GetRepository(ctx, namedRef, config)
|
||||
distrepo, err := s.backend.GetRepository(ctx, namedRef, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -72,6 +72,6 @@ type VolumeBackend interface {
|
|||
// ImageBackend is used by an executor to perform image operations
|
||||
type ImageBackend interface {
|
||||
PullImage(ctx context.Context, image, tag string, platform *specs.Platform, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
||||
GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, bool, error)
|
||||
GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, error)
|
||||
LookupImage(name string) (*types.ImageInspect, error)
|
||||
}
|
||||
|
|
|
@ -633,7 +633,7 @@ func (c *Cluster) imageWithDigestString(ctx context.Context, image string, authC
|
|||
return "", errors.Errorf("image reference not tagged: %s", image)
|
||||
}
|
||||
|
||||
repo, _, err := c.config.ImageBackend.GetRepository(ctx, taggedRef, authConfig)
|
||||
repo, err := c.config.ImageBackend.GetRepository(ctx, taggedRef, authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
progressutils "github.com/docker/docker/distribution/utils"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/docker/docker/registry"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -110,41 +109,36 @@ func (i *ImageService) pullImageWithReference(ctx context.Context, ref reference
|
|||
}
|
||||
|
||||
// GetRepository returns a repository from the registry.
|
||||
func (i *ImageService) GetRepository(ctx context.Context, ref reference.Named, authConfig *types.AuthConfig) (dist.Repository, bool, error) {
|
||||
func (i *ImageService) GetRepository(ctx context.Context, ref reference.Named, authConfig *types.AuthConfig) (dist.Repository, error) {
|
||||
// get repository info
|
||||
repoInfo, err := i.registryService.ResolveRepository(ref)
|
||||
if err != nil {
|
||||
return nil, false, errdefs.InvalidParameter(err)
|
||||
return nil, errdefs.InvalidParameter(err)
|
||||
}
|
||||
// makes sure name is not empty or `scratch`
|
||||
if err := distribution.ValidateRepoName(repoInfo.Name); err != nil {
|
||||
return nil, false, errdefs.InvalidParameter(err)
|
||||
return nil, errdefs.InvalidParameter(err)
|
||||
}
|
||||
|
||||
// get endpoints
|
||||
endpoints, err := i.registryService.LookupPullEndpoints(reference.Domain(repoInfo.Name))
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// retrieve repository
|
||||
var (
|
||||
confirmedV2 bool
|
||||
repository dist.Repository
|
||||
lastError error
|
||||
)
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
if endpoint.Version == registry.APIVersion1 {
|
||||
continue
|
||||
}
|
||||
|
||||
repository, confirmedV2, lastError = distribution.NewV2Repository(ctx, repoInfo, endpoint, nil, authConfig, "pull")
|
||||
if lastError == nil && confirmedV2 {
|
||||
repository, lastError = distribution.NewV2Repository(ctx, repoInfo, endpoint, nil, authConfig, "pull")
|
||||
if lastError == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return repository, confirmedV2, lastError
|
||||
return repository, lastError
|
||||
}
|
||||
|
||||
func tempLease(ctx context.Context, mgr leases.Manager) (context.Context, func(context.Context) error, error) {
|
||||
|
|
|
@ -34,10 +34,6 @@ func (e ErrNoSupport) Error() string {
|
|||
type fallbackError struct {
|
||||
// err is the error being wrapped.
|
||||
err error
|
||||
// confirmedV2 is set to true if it was confirmed that the registry
|
||||
// supports the v2 protocol. This is used to limit fallbacks to the v1
|
||||
// protocol.
|
||||
confirmedV2 bool
|
||||
// transportOK is set to true if we managed to speak HTTP with the
|
||||
// registry. This confirms that we're using appropriate TLS settings
|
||||
// (or lack of TLS).
|
||||
|
@ -53,15 +49,6 @@ func (f fallbackError) Cause() error {
|
|||
return f.err
|
||||
}
|
||||
|
||||
// shouldV2Fallback returns true if this error is a reason to fall back to v1.
|
||||
func shouldV2Fallback(err errcode.Error) bool {
|
||||
switch err.Code {
|
||||
case errcode.ErrorCodeUnauthorized, v2.ErrorCodeManifestUnknown, v2.ErrorCodeNameUnknown:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type notFoundError struct {
|
||||
cause errcode.Error
|
||||
ref reference.Named
|
||||
|
@ -141,7 +128,7 @@ func continueOnError(err error, mirrorEndpoint bool) bool {
|
|||
case ErrNoSupport:
|
||||
return continueOnError(v.Err, mirrorEndpoint)
|
||||
case errcode.Error:
|
||||
return mirrorEndpoint || shouldV2Fallback(v)
|
||||
return mirrorEndpoint
|
||||
case *client.UnexpectedHTTPResponseError:
|
||||
return true
|
||||
case ImageConfigPullError:
|
||||
|
|
|
@ -24,11 +24,7 @@ type Puller interface {
|
|||
Pull(ctx context.Context, ref reference.Named, platform *specs.Platform) error
|
||||
}
|
||||
|
||||
// newPuller returns a Puller interface that will pull from either a v1 or v2
|
||||
// registry. The endpoint argument contains a Version field that determines
|
||||
// whether a v1 or v2 puller will be created. The other parameters are passed
|
||||
// through to the underlying puller implementation for use during the actual
|
||||
// pull operation.
|
||||
// newPuller returns a Puller interface that will pull from a v2 registry.
|
||||
func newPuller(endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, imagePullConfig *ImagePullConfig, local ContentStore) (Puller, error) {
|
||||
switch endpoint.Version {
|
||||
case registry.APIVersion2:
|
||||
|
@ -78,26 +74,12 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo
|
|||
// error is the ones from v2 endpoints not v1.
|
||||
discardNoSupportErrors bool
|
||||
|
||||
// confirmedV2 is set to true if a pull attempt managed to
|
||||
// confirm that it was talking to a v2 registry. This will
|
||||
// prevent fallback to the v1 protocol.
|
||||
confirmedV2 bool
|
||||
|
||||
// confirmedTLSRegistries is a map indicating which registries
|
||||
// are known to be using TLS. There should never be a plaintext
|
||||
// retry for any of these.
|
||||
confirmedTLSRegistries = make(map[string]struct{})
|
||||
)
|
||||
for _, endpoint := range endpoints {
|
||||
if imagePullConfig.RequireSchema2 && endpoint.Version == registry.APIVersion1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if confirmedV2 && endpoint.Version == registry.APIVersion1 {
|
||||
logrus.Debugf("Skipping v1 endpoint %s because v2 registry was detected", endpoint.URL)
|
||||
continue
|
||||
}
|
||||
|
||||
if endpoint.URL.Scheme != "https" {
|
||||
if _, confirmedTLS := confirmedTLSRegistries[endpoint.URL.Host]; confirmedTLS {
|
||||
logrus.Debugf("Skipping non-TLS endpoint %s for host/port that appears to use TLS", endpoint.URL)
|
||||
|
@ -122,7 +104,6 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo
|
|||
default:
|
||||
if fallbackErr, ok := err.(fallbackError); ok {
|
||||
fallback = true
|
||||
confirmedV2 = confirmedV2 || fallbackErr.confirmedV2
|
||||
if fallbackErr.transportOK && endpoint.URL.Scheme == "https" {
|
||||
confirmedTLSRegistries[endpoint.URL.Host] = struct{}{}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -19,8 +18,6 @@ import (
|
|||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
"github.com/docker/docker/distribution/metadata"
|
||||
"github.com/docker/docker/distribution/xfer"
|
||||
|
@ -61,15 +58,12 @@ type v2Puller struct {
|
|||
config *ImagePullConfig
|
||||
repoInfo *registry.RepositoryInfo
|
||||
repo distribution.Repository
|
||||
// confirmedV2 is set to true if we confirm we're talking to a v2
|
||||
// registry. This is used to limit fallbacks to the v1 protocol.
|
||||
confirmedV2 bool
|
||||
manifestStore *manifestStore
|
||||
}
|
||||
|
||||
func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform *specs.Platform) (err error) {
|
||||
// TODO(tiborvass): was ReceiveTimeout
|
||||
p.repo, p.confirmedV2, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
|
||||
p.repo, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
|
||||
if err != nil {
|
||||
logrus.Warnf("Error getting v2 registry: %v", err)
|
||||
return err
|
||||
|
@ -87,7 +81,6 @@ func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform *spec
|
|||
if continueOnError(err, p.endpoint.Mirror) {
|
||||
return fallbackError{
|
||||
err: err,
|
||||
confirmedV2: p.confirmedV2,
|
||||
transportOK: true,
|
||||
}
|
||||
}
|
||||
|
@ -105,16 +98,9 @@ func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named, pl
|
|||
} else {
|
||||
tags, err := p.repo.Tags(ctx).All(ctx)
|
||||
if err != nil {
|
||||
// If this repository doesn't exist on V2, we should
|
||||
// permit a fallback to V1.
|
||||
return allowV1Fallback(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// The v2 registry knows about this repository, so we will not
|
||||
// allow fallback to the v1 protocol even if we encounter an
|
||||
// error later on.
|
||||
p.confirmedV2 = true
|
||||
|
||||
for _, tag := range tags {
|
||||
tagRef, err := reference.WithTag(ref, tag)
|
||||
if err != nil {
|
||||
|
@ -353,7 +339,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform
|
|||
tagService := p.repo.Tags(ctx)
|
||||
desc, err := tagService.Get(ctx, tagged.Tag())
|
||||
if err != nil {
|
||||
return false, allowV1Fallback(err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
dgst = desc.Digest
|
||||
|
@ -427,10 +413,6 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform
|
|||
}
|
||||
}
|
||||
|
||||
// If manSvc.Get succeeded, we can be confident that the registry on
|
||||
// the other side speaks the v2 protocol.
|
||||
p.confirmedV2 = true
|
||||
|
||||
logrus.Debugf("Pulling ref from V2 registry: %s", reference.FamiliarString(ref))
|
||||
progress.Message(p.config.ProgressOutput, tagOrDigest, "Pulling from "+reference.FamiliarName(p.repo.Named()))
|
||||
|
||||
|
@ -945,39 +927,6 @@ func schema2ManifestDigest(ref reference.Named, mfst distribution.Manifest) (dig
|
|||
return digest.FromBytes(canonical), nil
|
||||
}
|
||||
|
||||
// allowV1Fallback checks if the error is a possible reason to fallback to v1
|
||||
// (even if confirmedV2 has been set already), and if so, wraps the error in
|
||||
// a fallbackError with confirmedV2 set to false. Otherwise, it returns the
|
||||
// error unmodified.
|
||||
func allowV1Fallback(err error) error {
|
||||
switch v := err.(type) {
|
||||
case errcode.Errors:
|
||||
if len(v) != 0 {
|
||||
if v0, ok := v[0].(errcode.Error); ok && shouldV2Fallback(v0) {
|
||||
return fallbackError{
|
||||
err: err,
|
||||
confirmedV2: false,
|
||||
transportOK: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
case errcode.Error:
|
||||
if shouldV2Fallback(v) {
|
||||
return fallbackError{
|
||||
err: err,
|
||||
confirmedV2: false,
|
||||
transportOK: true,
|
||||
}
|
||||
}
|
||||
case *url.Error:
|
||||
if v.Err == auth.ErrNoBasicAuthCredentials {
|
||||
return fallbackError{err: err, confirmedV2: false}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func verifySchema1Manifest(signedManifest *schema1.SignedManifest, ref reference.Reference) (m *schema1.Manifest, err error) {
|
||||
// If pull by digest, then verify the manifest digest. NOTE: It is
|
||||
// important to do this first, before any other content validation. If the
|
||||
|
|
|
@ -73,11 +73,6 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
|
|||
var (
|
||||
lastErr error
|
||||
|
||||
// confirmedV2 is set to true if a push attempt managed to
|
||||
// confirm that it was talking to a v2 registry. This will
|
||||
// prevent fallback to the v1 protocol.
|
||||
confirmedV2 bool
|
||||
|
||||
// confirmedTLSRegistries is a map indicating which registries
|
||||
// are known to be using TLS. There should never be a plaintext
|
||||
// retry for any of these.
|
||||
|
@ -85,14 +80,6 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
|
|||
)
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
if imagePushConfig.RequireSchema2 && endpoint.Version == registry.APIVersion1 {
|
||||
continue
|
||||
}
|
||||
if confirmedV2 && endpoint.Version == registry.APIVersion1 {
|
||||
logrus.Debugf("Skipping v1 endpoint %s because v2 registry was detected", endpoint.URL)
|
||||
continue
|
||||
}
|
||||
|
||||
if endpoint.URL.Scheme != "https" {
|
||||
if _, confirmedTLS := confirmedTLSRegistries[endpoint.URL.Host]; confirmedTLS {
|
||||
logrus.Debugf("Skipping non-TLS endpoint %s for host/port that appears to use TLS", endpoint.URL)
|
||||
|
@ -114,7 +101,6 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
|
|||
case <-ctx.Done():
|
||||
default:
|
||||
if fallbackErr, ok := err.(fallbackError); ok {
|
||||
confirmedV2 = confirmedV2 || fallbackErr.confirmedV2
|
||||
if fallbackErr.transportOK && endpoint.URL.Scheme == "https" {
|
||||
confirmedTLSRegistries[endpoint.URL.Host] = struct{}{}
|
||||
}
|
||||
|
|
|
@ -53,16 +53,13 @@ type pushState struct {
|
|||
// involve the same layers. It is also used to fill in digest and size
|
||||
// information when building the manifest.
|
||||
remoteLayers map[layer.DiffID]distribution.Descriptor
|
||||
// confirmedV2 is set to true if we confirm we're talking to a v2
|
||||
// registry. This is used to limit fallbacks to the v1 protocol.
|
||||
confirmedV2 bool
|
||||
hasAuthInfo bool
|
||||
}
|
||||
|
||||
func (p *v2Pusher) Push(ctx context.Context) (err error) {
|
||||
p.pushState.remoteLayers = make(map[layer.DiffID]distribution.Descriptor)
|
||||
|
||||
p.repo, p.pushState.confirmedV2, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "push", "pull")
|
||||
p.repo, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "push", "pull")
|
||||
p.pushState.hasAuthInfo = p.config.AuthConfig.RegistryToken != "" || (p.config.AuthConfig.Username != "" && p.config.AuthConfig.Password != "")
|
||||
if err != nil {
|
||||
logrus.Debugf("Error getting v2 registry: %v", err)
|
||||
|
@ -73,7 +70,6 @@ func (p *v2Pusher) Push(ctx context.Context) (err error) {
|
|||
if continueOnError(err, p.endpoint.Mirror) {
|
||||
return fallbackError{
|
||||
err: err,
|
||||
confirmedV2: p.pushState.confirmedV2,
|
||||
transportOK: true,
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +366,6 @@ func (pd *v2PushDescriptor) Upload(ctx context.Context, progressOutput progress.
|
|||
err.Descriptor.MediaType = schema2.MediaTypeLayer
|
||||
|
||||
pd.pushState.Lock()
|
||||
pd.pushState.confirmedV2 = true
|
||||
pd.pushState.remoteLayers[diffID] = err.Descriptor
|
||||
pd.pushState.Unlock()
|
||||
|
||||
|
@ -510,8 +505,6 @@ func (pd *v2PushDescriptor) uploadUsingSession(
|
|||
}
|
||||
|
||||
pd.pushState.Lock()
|
||||
// If Commit succeeded, that's an indication that the remote registry speaks the v2 protocol.
|
||||
pd.pushState.confirmedV2 = true
|
||||
pd.pushState.remoteLayers[diffID] = desc
|
||||
pd.pushState.Unlock()
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ func TestWhenEmptyAuthConfig(t *testing.T) {
|
|||
Scheme: "https",
|
||||
Host: "index.docker.io",
|
||||
},
|
||||
Version: registry.APIVersion1,
|
||||
Version: registry.APIVersion2,
|
||||
TrimHostname: true,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func init() {
|
|||
func NewV2Repository(
|
||||
ctx context.Context, repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint,
|
||||
metaHeaders http.Header, authConfig *types.AuthConfig, actions ...string,
|
||||
) (repo distribution.Repository, foundVersion bool, err error) {
|
||||
) (repo distribution.Repository, err error) {
|
||||
repoName := repoInfo.Name.Name()
|
||||
// If endpoint does not support CanonicalName, use the RemoteName instead
|
||||
if endpoint.TrimHostname {
|
||||
|
@ -84,16 +84,15 @@ func NewV2Repository(
|
|||
modifiers := registry.Headers(dockerversion.DockerUserAgent(ctx), metaHeaders)
|
||||
authTransport := transport.NewTransport(base, modifiers...)
|
||||
|
||||
challengeManager, foundVersion, err := registry.PingV2Registry(endpoint.URL, authTransport)
|
||||
challengeManager, err := registry.PingV2Registry(endpoint.URL, authTransport)
|
||||
if err != nil {
|
||||
transportOK := false
|
||||
if responseErr, ok := err.(registry.PingResponseError); ok {
|
||||
transportOK = true
|
||||
err = responseErr.Err
|
||||
}
|
||||
return nil, foundVersion, fallbackError{
|
||||
return nil, fallbackError{
|
||||
err: err,
|
||||
confirmedV2: foundVersion,
|
||||
transportOK: transportOK,
|
||||
}
|
||||
}
|
||||
|
@ -123,9 +122,8 @@ func NewV2Repository(
|
|||
|
||||
repoNameRef, err := reference.WithName(repoName)
|
||||
if err != nil {
|
||||
return nil, foundVersion, fallbackError{
|
||||
return nil, fallbackError{
|
||||
err: err,
|
||||
confirmedV2: foundVersion,
|
||||
transportOK: true,
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +132,6 @@ func NewV2Repository(
|
|||
if err != nil {
|
||||
err = fallbackError{
|
||||
err: err,
|
||||
confirmedV2: foundVersion,
|
||||
transportOK: true,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ func testTokenPassThru(t *testing.T, ts *httptest.Server) {
|
|||
}
|
||||
p := puller.(*v2Puller)
|
||||
ctx := context.Background()
|
||||
p.repo, _, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
|
||||
p.repo, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -87,26 +87,19 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
|
|||
|
||||
logrus.Debugf("attempting v2 login to registry endpoint %s", endpointStr)
|
||||
|
||||
loginClient, foundV2, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil)
|
||||
loginClient, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
|
||||
if err != nil {
|
||||
if !foundV2 {
|
||||
err = fallbackError{err: err}
|
||||
}
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
resp, err := loginClient.Do(req)
|
||||
if err != nil {
|
||||
err = translateV2AuthError(err)
|
||||
if !foundV2 {
|
||||
err = fallbackError{err: err}
|
||||
}
|
||||
|
||||
return "", "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
@ -117,19 +110,13 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
|
|||
|
||||
// TODO(dmcgowan): Attempt to further interpret result, status code and error code string
|
||||
err = errors.Errorf("login attempt to %s failed with status: %d %s", endpointStr, resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
if !foundV2 {
|
||||
err = fallbackError{err: err}
|
||||
}
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifiers []transport.RequestModifier, creds auth.CredentialStore, scopes []auth.Scope) (*http.Client, bool, error) {
|
||||
challengeManager, foundV2, err := PingV2Registry(endpoint, authTransport)
|
||||
func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifiers []transport.RequestModifier, creds auth.CredentialStore, scopes []auth.Scope) (*http.Client, error) {
|
||||
challengeManager, err := PingV2Registry(endpoint, authTransport)
|
||||
if err != nil {
|
||||
if !foundV2 {
|
||||
err = fallbackError{err: err}
|
||||
}
|
||||
return nil, foundV2, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokenHandlerOptions := auth.TokenHandlerOptions{
|
||||
|
@ -147,8 +134,7 @@ func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifi
|
|||
return &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: 15 * time.Second,
|
||||
}, foundV2, nil
|
||||
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ConvertToHostname converts a registry url which has http|https prepended
|
||||
|
@ -197,18 +183,9 @@ func (err PingResponseError) Error() string {
|
|||
}
|
||||
|
||||
// PingV2Registry attempts to ping a v2 registry and on success return a
|
||||
// challenge manager for the supported authentication types and
|
||||
// whether v2 was confirmed by the response. If a response is received but
|
||||
// cannot be interpreted a PingResponseError will be returned.
|
||||
func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.Manager, bool, error) {
|
||||
var (
|
||||
foundV2 = false
|
||||
v2Version = auth.APIVersion{
|
||||
Type: "registry",
|
||||
Version: "2.0",
|
||||
}
|
||||
)
|
||||
|
||||
// challenge manager for the supported authentication types.
|
||||
// If a response is received but cannot be interpreted, a PingResponseError will be returned.
|
||||
func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.Manager, error) {
|
||||
pingClient := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: 15 * time.Second,
|
||||
|
@ -216,32 +193,20 @@ func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.M
|
|||
endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/"
|
||||
req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
resp, err := pingClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
versions := auth.APIVersions(resp, DefaultRegistryVersionHeader)
|
||||
for _, pingVersion := range versions {
|
||||
if pingVersion == v2Version {
|
||||
// The version header indicates we're definitely
|
||||
// talking to a v2 registry. So don't allow future
|
||||
// fallbacks to the v1 protocol.
|
||||
|
||||
foundV2 = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
challengeManager := challenge.NewSimpleManager()
|
||||
if err := challengeManager.AddResponse(resp); err != nil {
|
||||
return nil, foundV2, PingResponseError{
|
||||
return nil, PingResponseError{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return challengeManager, foundV2, nil
|
||||
return challengeManager, nil
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ type V1Endpoint struct {
|
|||
}
|
||||
|
||||
// NewV1Endpoint parses the given address to return a registry endpoint.
|
||||
// TODO: remove. This is only used by search.
|
||||
func NewV1Endpoint(index *registrytypes.IndexInfo, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
|
||||
tlsConfig, err := newTLSConfig(index.Name, index.Secure)
|
||||
if err != nil {
|
||||
|
|
|
@ -131,16 +131,7 @@ func (s *DefaultService) Auth(ctx context.Context, authConfig *types.AuthConfig,
|
|||
}
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
status, token, err = loginV2(authConfig, endpoint, userAgent)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if fErr, ok := err.(fallbackError); ok {
|
||||
logrus.WithError(fErr.err).Infof("Error logging in to endpoint, trying next endpoint")
|
||||
continue
|
||||
}
|
||||
|
||||
return "", "", err
|
||||
return loginV2(authConfig, endpoint, userAgent)
|
||||
}
|
||||
|
||||
return "", "", err
|
||||
|
@ -194,14 +185,14 @@ func (s *DefaultService) Search(ctx context.Context, term string, limit int, aut
|
|||
}
|
||||
|
||||
modifiers := Headers(userAgent, nil)
|
||||
v2Client, foundV2, err := v2AuthHTTPClient(endpoint.URL, endpoint.client.Transport, modifiers, creds, scopes)
|
||||
v2Client, err := v2AuthHTTPClient(endpoint.URL, endpoint.client.Transport, modifiers, creds, scopes)
|
||||
if err != nil {
|
||||
if fErr, ok := err.(fallbackError); ok {
|
||||
logrus.Errorf("Cannot use identity token for search, v2 auth not supported: %v", fErr.err)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else if foundV2 {
|
||||
} else {
|
||||
// Copy non transport http client features
|
||||
v2Client.Timeout = endpoint.client.Timeout
|
||||
v2Client.CheckRedirect = endpoint.client.CheckRedirect
|
||||
|
|
Loading…
Reference in a new issue