Skip to content

Commit 9bc2315

Browse files
Merge pull request #3109 from bainsy88/issue_3076
Add code to return errors from registries
2 parents b7183a0 + d15832a commit 9bc2315

5 files changed

Lines changed: 525 additions & 1 deletion

File tree

remotes/docker/fetcher.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package docker
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"fmt"
2223
"io"
2324
"io/ioutil"
@@ -28,6 +29,7 @@ import (
2829
"github.com/containerd/containerd/errdefs"
2930
"github.com/containerd/containerd/images"
3031
"github.com/containerd/containerd/log"
32+
"github.com/docker/distribution/registry/api/errcode"
3133
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
3234
"github.com/pkg/errors"
3335
"github.com/sirupsen/logrus"
@@ -102,10 +104,18 @@ func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int
102104
// can discard the bytes, hiding the seek behavior from the
103105
// implementation.
104106

105-
resp.Body.Close()
107+
defer resp.Body.Close()
106108
if resp.StatusCode == http.StatusNotFound {
107109
return nil, errors.Wrapf(errdefs.ErrNotFound, "content at %v not found", u)
108110
}
111+
body, err := ioutil.ReadAll(resp.Body)
112+
if err == nil {
113+
dockerErr := errcode.Errors{}
114+
err := json.Unmarshal(body, &dockerErr)
115+
if err == nil && dockerErr.Len() > 0 {
116+
return nil, errors.Errorf("unexpected status code %v: %s - Server message: %s", u, resp.Status, dockerErr.Error())
117+
}
118+
}
109119
return nil, errors.Errorf("unexpected status code %v: %v", u, resp.Status)
110120
}
111121
if offset > 0 {

remotes/docker/fetcher_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@ package docker
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"fmt"
23+
"io"
2224
"io/ioutil"
2325
"math/rand"
2426
"net/http"
2527
"net/http/httptest"
2628
"testing"
29+
30+
"github.com/docker/distribution/registry/api/errcode"
31+
"github.com/pkg/errors"
32+
"gotest.tools/assert"
2733
)
2834

2935
func TestFetcherOpen(t *testing.T) {
@@ -92,3 +98,66 @@ func TestFetcherOpen(t *testing.T) {
9298
t.Fatal("expected error opening with invalid server response")
9399
}
94100
}
101+
102+
// New set of tests to test new error cases
103+
func TestDockerFetcherOpen(t *testing.T) {
104+
tests := []struct {
105+
name string
106+
mockedStatus int
107+
mockedErr error
108+
want io.ReadCloser
109+
wantErr bool
110+
wantServerMessageError bool
111+
wantPlainError bool
112+
}{
113+
{
114+
name: "should return status and error.message if it exists if the registry request fails",
115+
mockedStatus: 500,
116+
mockedErr: errcode.Errors{errcode.Error{
117+
Code: errcode.ErrorCodeUnknown,
118+
Message: "Test Error",
119+
}},
120+
want: nil,
121+
wantErr: true,
122+
wantServerMessageError: true,
123+
},
124+
{
125+
name: "should return just status if the registry request fails and does not return a docker error",
126+
mockedStatus: 500,
127+
mockedErr: fmt.Errorf("Non-docker error"),
128+
want: nil,
129+
wantErr: true,
130+
wantPlainError: true,
131+
},
132+
}
133+
for _, tt := range tests {
134+
t.Run(tt.name, func(t *testing.T) {
135+
136+
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
137+
rw.WriteHeader(tt.mockedStatus)
138+
bytes, _ := json.Marshal(tt.mockedErr)
139+
rw.Write(bytes)
140+
}))
141+
defer s.Close()
142+
143+
r := dockerFetcher{&dockerBase{
144+
client: s.Client(),
145+
}}
146+
147+
got, err := r.open(context.TODO(), s.URL, "", 0)
148+
assert.Equal(t, tt.wantErr, (err != nil))
149+
assert.Equal(t, tt.want, got)
150+
if tt.wantErr {
151+
var expectedError error
152+
if tt.wantServerMessageError {
153+
expectedError = errors.Errorf("unexpected status code %v: %v %s - Server message: %s", s.URL, tt.mockedStatus, http.StatusText(tt.mockedStatus), tt.mockedErr.Error())
154+
} else if tt.wantPlainError {
155+
expectedError = errors.Errorf("unexpected status code %v: %v %s", s.URL, tt.mockedStatus, http.StatusText(tt.mockedStatus))
156+
}
157+
assert.Equal(t, expectedError.Error(), err.Error())
158+
159+
}
160+
161+
})
162+
}
163+
}

vendor/github.com/docker/distribution/registry/api/errcode/errors.go

Lines changed: 267 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)