diff --git a/lib/imagec/docker.go b/lib/imagec/docker.go index 92d43b3a2b..c43e09ba27 100644 --- a/lib/imagec/docker.go +++ b/lib/imagec/docker.go @@ -323,7 +323,7 @@ func tagOrDigest(r reference.Named, tag string) string { // FetchImageManifest fetches the image manifest file func FetchImageManifest(ctx context.Context, options Options, schemaVersion int, progressOutput progress.Output) (interface{}, string, error) { - defer trace.End(trace.Begin(options.Reference.String())) + defer trace.End(trace.Begin(fmt.Sprintf("url = %s, schema = %d", options.Reference.String(), schemaVersion))) if schemaVersion != 1 && schemaVersion != 2 { return nil, "", fmt.Errorf("Unknown schema version %d requested!", schemaVersion) @@ -355,6 +355,7 @@ func FetchImageManifest(ctx context.Context, options Options, schemaVersion int, manifestFileName, err := fetcher.Fetch(ctx, url, &reqHeaders, true, progressOutput) if err != nil { + log.Debugf("Failed to fetch manifest: %s", err.Error()) return nil, "", err } diff --git a/lib/imagec/imagec.go b/lib/imagec/imagec.go index b9b47b00a2..7c8f4db01f 100644 --- a/lib/imagec/imagec.go +++ b/lib/imagec/imagec.go @@ -138,7 +138,7 @@ var ( const ( // DefaultDockerURL holds the URL of Docker registry - DefaultDockerURL = "registry.hub.docker.com" + DefaultDockerURL = "registry-1.docker.io" // DefaultDestination specifies the default directory to use DefaultDestination = "images" diff --git a/lib/imagec/imagec_test.go b/lib/imagec/imagec_test.go index fdfc6acfd8..0e5c4e482f 100644 --- a/lib/imagec/imagec_test.go +++ b/lib/imagec/imagec_test.go @@ -601,8 +601,8 @@ func TestFetchScenarios(t *testing.T) { // valid token but image is missing we shouldn't retry _, _, err = FetchImageManifest(ctx, ic.Options, 1, ic.progressOutput) if err != nil { - // we should get a ImageNotFoundError - if _, imageErr := err.(urlfetcher.ImageNotFoundError); !imageErr { + // we should get a AccessDenied + if _, imageErr := err.(urlfetcher.AccessDenied); !imageErr { t.Errorf(err.Error()) } } diff --git a/pkg/fetcher/errors.go b/pkg/fetcher/errors.go index cbd8fbcde6..0d7ae8a799 100644 --- a/pkg/fetcher/errors.go +++ b/pkg/fetcher/errors.go @@ -56,3 +56,17 @@ type AuthTokenError struct { func (e AuthTokenError) Error() string { return fmt.Sprintf("Failed to fetch auth token from %s", e.TokenServer.Host) } + +// AccessDenied is returned when the resource requested +type AccessDenied struct { + Err error + res string +} + +func (e AccessDenied) Error() string { + if e.res == "" { + return fmt.Sprintf("Access denied to requested resource") + } + + return fmt.Sprintf("Access denied to %s", e.res) +} diff --git a/pkg/fetcher/fetcher.go b/pkg/fetcher/fetcher.go index b49073f87e..5dd1e36d87 100644 --- a/pkg/fetcher/fetcher.go +++ b/pkg/fetcher/fetcher.go @@ -172,7 +172,7 @@ func (u *URLFetcher) Fetch(ctx context.Context, url *url.URL, reqHdrs *http.Head } switch err := err.(type) { - case DoNotRetry, TagNotFoundError, ImageNotFoundError: + case DoNotRetry, TagNotFoundError, ImageNotFoundError, AccessDenied: log.Debugf("Error: %s", err.Error()) return "", err } @@ -280,10 +280,10 @@ func (u *URLFetcher) fetch(ctx context.Context, url *url.URL, reqHdrs *http.Head if u.IsStatusUnauthorized() { hdr := res.Header.Get("www-authenticate") - // check if image is non-existent (#757) + // Fix insufficient_scope return value. + // https://github.com/vmware/vic/blob/master/vendor/github.com/docker/distribution/registry/client/errors.go#L112 if strings.Contains(hdr, "error=\"insufficient_scope\"") { - err = fmt.Errorf("image not found") - return nil, nil, ImageNotFoundError{Err: err} + return nil, nil, AccessDenied{Err: err, res: url.String()} } else if strings.Contains(hdr, "error=\"invalid_token\"") { return nil, nil, fmt.Errorf("not authorized") } else {