Filtered out unfriendly error from docker when registry is not reachable(code: 502, 503, 504)

This commit is contained in:
Dawn Chen 2015-06-04 17:37:07 -07:00
parent bbea2863c2
commit 636b40ffa1
2 changed files with 56 additions and 2 deletions

View File

@ -19,6 +19,7 @@ package dockertools
import (
"fmt"
"math/rand"
"net/http"
"os"
"strconv"
"strings"
@ -31,6 +32,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
utilerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/parsers"
docker "github.com/fsouza/go-dockerclient"
"github.com/golang/glog"
@ -113,6 +115,22 @@ func parseImageName(image string) (string, string) {
return parsers.ParseRepositoryTag(image)
}
func filterHTTPError(err error, image string) error {
// docker/docker/pull/11314 prints detailed error info for docker pull.
// When it hits 502, it returns a verbose html output including an inline svg,
// which makes the output of kubectl get pods much harder to parse.
// Here converts such verbose output to a concise one.
jerr, ok := err.(*jsonmessage.JSONError)
if ok && (jerr.Code == http.StatusBadGateway ||
jerr.Code == http.StatusServiceUnavailable ||
jerr.Code == http.StatusGatewayTimeout) {
glog.V(2).Infof("Pulling image %q failed: %v", image, err)
return fmt.Errorf("image pull failed for %s because the registry is temporarily unavailbe.", image)
} else {
return err
}
}
func (p dockerPuller) Pull(image string, secrets []api.Secret) error {
repoToPull, tag := parseImageName(image)
@ -149,7 +167,7 @@ func (p dockerPuller) Pull(image string, secrets []api.Secret) error {
return fmt.Errorf("image pull failed for %s, this may be because there are no credentials on this request. details: (%v)", image, err)
}
return err
return filterHTTPError(err, image)
}
var pullErrs []error
@ -160,7 +178,7 @@ func (p dockerPuller) Pull(image string, secrets []api.Secret) error {
return nil
}
pullErrs = append(pullErrs, err)
pullErrs = append(pullErrs, filterHTTPError(err, image))
}
return utilerrors.NewAggregate(pullErrs)

View File

@ -22,6 +22,7 @@ import (
"hash/adler32"
"reflect"
"sort"
"strings"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@ -31,6 +32,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/docker/docker/pkg/jsonmessage"
docker "github.com/fsouza/go-dockerclient"
)
@ -238,6 +240,40 @@ func TestPullWithNoSecrets(t *testing.T) {
}
}
func TestPullWithJSONError(t *testing.T) {
tests := map[string]struct {
imageName string
err error
expectedError string
}{
"Json error": {
"ubuntu",
&jsonmessage.JSONError{Code: 50, Message: "Json error"},
"Json error",
},
"Bad gateway": {
"ubuntu",
&jsonmessage.JSONError{Code: 502, Message: "<!doctype html>\n<html class=\"no-js\" lang=\"\">\n <head>\n </head>\n <body>\n <h1>Oops, there was an error!</h1>\n <p>We have been contacted of this error, feel free to check out <a href=\"http://status.docker.com/\">status.docker.com</a>\n to see if there is a bigger issue.</p>\n\n </body>\n</html>"},
"because the registry is temporarily unavailbe",
},
}
for i, test := range tests {
fakeKeyring := &credentialprovider.FakeKeyring{}
fakeClient := &FakeDockerClient{
Errors: map[string]error{"pull": test.err},
}
puller := &dockerPuller{
client: fakeClient,
keyring: fakeKeyring,
}
err := puller.Pull(test.imageName, []api.Secret{})
if err == nil || !strings.Contains(err.Error(), test.expectedError) {
t.Errorf("%d: expect error %s, got : %s", i, test.expectedError, err)
continue
}
}
}
func TestPullWithSecrets(t *testing.T) {
// auth value is equivalent to: "username":"passed-user","password":"passed-password"
dockerCfg := map[string]map[string]string{"index.docker.io/v1/": {"email": "passed-email", "auth": "cGFzc2VkLXVzZXI6cGFzc2VkLXBhc3N3b3Jk"}}