Skip to content

Commit

Permalink
fix: report the real error cause of pulling image
Browse files Browse the repository at this point in the history
Signed-off-by: zhijin <[email protected]>
  • Loading branch information
zhijin authored and zhuangqh committed Oct 22, 2019
1 parent 169018c commit 8bddcd4
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 4 deletions.
2 changes: 2 additions & 0 deletions apis/server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ func HandleErrorResponse(w http.ResponseWriter, err error) {
code = http.StatusConflict
} else if errtypes.IsNotModified(err) {
code = http.StatusNotModified
} else if errtypes.IsInvalidAuthorization(err) {
code = http.StatusForbidden
}

w.Header().Set("Content-Type", "application/json")
Expand Down
1 change: 0 additions & 1 deletion ctrd/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ func (c *Client) PushImage(ctx context.Context, ref string, authConfig *types.Au
func (c *Client) ResolveImage(ctx context.Context, nameRef string, refs []string, authConfig *types.AuthConfig, opts docker.ResolverOptions) (remotes.Resolver, string, error) {
resolver, availableRef, err := c.getResolver(ctx, authConfig, nameRef, refs, opts)
if err != nil {
log.With(nil).Errorf("image ref not found %s", nameRef)
return nil, "", err
}

Expand Down
12 changes: 10 additions & 2 deletions ctrd/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (c *Client) getResolver(ctx context.Context, authConfig *types.AuthConfig,
var (
availableRef string
opt docker.ResolverOptions
resolveErr error
)

for _, ref := range refs {
Expand Down Expand Up @@ -158,15 +159,22 @@ func (c *Client) getResolver(ctx context.Context, authConfig *types.AuthConfig,

resolver := docker.NewResolver(opt)

if _, _, err := resolver.Resolve(ctx, namedRef.String()); err == nil {
_, _, err = resolver.Resolve(ctx, namedRef.String())
if err == nil {
availableRef = namedRef.String()
break
}

if errors.Cause(err) == docker.ErrInvalidAuthorization {
resolveErr = errors.Wrap(errtypes.ErrInvalidAuthorization, err.Error())
} else {
resolveErr = errors.Wrap(errtypes.ErrNotfound, err.Error())
}
}

if availableRef == "" {
log.With(nil).Warnf("there is no available image reference after trying %+q", refs)
return nil, "", errtypes.ErrNotfound
return nil, "", resolveErr
}

refToName := map[string]string{
Expand Down
9 changes: 9 additions & 0 deletions pkg/errtypes/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ var (

// ErrPreCheckFailed represents that failed to pre check.
ErrPreCheckFailed = errorType{codePreCheckFailed, "pre check failed"}

// ErrInvalidAuthorization represents that authorization failed.
ErrInvalidAuthorization = errorType{codeInvalidAuthorization, "authorization failed"}
)

const (
Expand All @@ -51,6 +54,7 @@ const (
codeInUse
codeNotModified
codePreCheckFailed
codeInvalidAuthorization

// volume error code
codeVolumeExisted
Expand Down Expand Up @@ -102,6 +106,11 @@ func IsPreCheckFailed(err error) bool {
return checkError(err, codePreCheckFailed)
}

// IsInvalidAuthorization checks the errors is authorization failure or not.
func IsInvalidAuthorization(err error) bool {
return checkError(err, codeInvalidAuthorization)
}

func checkError(err error, code int) bool {
err = causeError(err)

Expand Down
15 changes: 14 additions & 1 deletion test/api_image_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (suite *APIImageCreateSuite) TestImageCreateNil(c *check.C) {
// TestImageCreateNonExistentImage tests pulling a non-existent image.
func (suite *APIImageCreateSuite) TestImageCreateNonExistentImage(c *check.C) {
q := url.Values{}
image := "qwefghjm:zxcvbn_efgh_nonexist"
image := "nginx:zxcvbn_efgh_nonexist"

q.Add("fromImage", image)
query := request.WithQuery(q)
Expand All @@ -60,6 +60,19 @@ func (suite *APIImageCreateSuite) TestImageCreateNonExistentImage(c *check.C) {
CheckRespStatus(c, resp, 404)
}

// TestImageCreateNoAuthority tests pulling a no authority image.
func (suite *APIImageCreateSuite) TestImageCreateNoAuthority(c *check.C) {
q := url.Values{}
image := "foobarnotexist_zzzz:zzz"

q.Add("fromImage", image)
query := request.WithQuery(q)

resp, err := request.Post("/images/create", query)
c.Assert(err, check.IsNil)
CheckRespStatus(c, resp, 403)
}

// TestImageCreateWithoutTag tests creating an image without tag, will use "latest" by default.
func (suite *APIImageCreateSuite) TestImageCreateWithoutTag(c *check.C) {
q := url.Values{}
Expand Down

0 comments on commit 8bddcd4

Please sign in to comment.