add test for manifest handler where storage driver fails

Signed-off-by: Yu Wang (UC) <yuwa@microsoft.com>
This commit is contained in:
yuwaMSFT2 2017-01-13 15:07:28 -08:00 committed by Yu Wang (UC)
parent 2e94c22fe4
commit 0bb696c5bf

View File

@ -3,6 +3,7 @@ package handlers
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -28,6 +29,8 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/errcode"
"github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/api/v2"
storagedriver "github.com/docker/distribution/registry/storage/driver"
"github.com/docker/distribution/registry/storage/driver/factory"
_ "github.com/docker/distribution/registry/storage/driver/testdriver" _ "github.com/docker/distribution/registry/storage/driver/testdriver"
"github.com/docker/distribution/testutil" "github.com/docker/distribution/testutil"
"github.com/docker/libtrust" "github.com/docker/libtrust"
@ -815,6 +818,93 @@ func TestManifestAPI(t *testing.T) {
testManifestAPIManifestList(t, env2, schema2Args) testManifestAPIManifestList(t, env2, schema2Args)
} }
// storageManifestErrDriverFactory implements the factory.StorageDriverFactory interface.
type storageManifestErrDriverFactory struct{}
const (
repositoryWithManifestNotFound = "manifesttagnotfound"
repositoryWithManifestInvalidPath = "manifestinvalidpath"
repositoryWithManifestBadLink = "manifestbadlink"
repositoryWithGenericStorageError = "genericstorageerr"
)
func (factory *storageManifestErrDriverFactory) Create(parameters map[string]interface{}) (storagedriver.StorageDriver, error) {
// Initialize the mock driver
var errGenericStorage = errors.New("generic storage error")
return &mockErrorDriver{
returnErrs: []mockErrorMapping{
{
pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithManifestNotFound),
content: nil,
err: storagedriver.PathNotFoundError{},
},
{
pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithManifestInvalidPath),
content: nil,
err: storagedriver.InvalidPathError{},
},
{
pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithManifestBadLink),
content: []byte("this is a bad sha"),
err: nil,
},
{
pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithGenericStorageError),
content: nil,
err: errGenericStorage,
},
},
}, nil
}
type mockErrorMapping struct {
pathMatch string
content []byte
err error
}
// mockErrorDriver implements StorageDriver to force storage error on manifest request
type mockErrorDriver struct {
storagedriver.StorageDriver
returnErrs []mockErrorMapping
}
func (dr *mockErrorDriver) GetContent(ctx context.Context, path string) ([]byte, error) {
for _, returns := range dr.returnErrs {
if strings.Contains(path, returns.pathMatch) {
return returns.content, returns.err
}
}
return nil, errors.New("Unknown storage error")
}
func TestGetManifestWithStorageError(t *testing.T) {
factory.Register("storagemanifesterror", &storageManifestErrDriverFactory{})
config := configuration.Configuration{
Storage: configuration.Storage{
"storagemanifesterror": configuration.Parameters{},
"maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{
"enabled": false,
}},
},
}
config.HTTP.Headers = headerConfig
env1 := newTestEnvWithConfig(t, &config)
defer env1.Shutdown()
repo, _ := reference.ParseNamed(repositoryWithManifestNotFound)
testManifestWithStorageError(t, env1, repo, http.StatusNotFound, v2.ErrorCodeManifestUnknown)
repo, _ = reference.ParseNamed(repositoryWithGenericStorageError)
testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown)
repo, _ = reference.ParseNamed(repositoryWithManifestInvalidPath)
testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown)
repo, _ = reference.ParseNamed(repositoryWithManifestBadLink)
testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown)
}
func TestManifestDelete(t *testing.T) { func TestManifestDelete(t *testing.T) {
schema1Repo, _ := reference.ParseNamed("foo/schema1") schema1Repo, _ := reference.ParseNamed("foo/schema1")
schema2Repo, _ := reference.ParseNamed("foo/schema2") schema2Repo, _ := reference.ParseNamed("foo/schema2")
@ -852,6 +942,26 @@ func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName reference.
checkResponse(t, "status of disabled delete of manifest", resp, http.StatusMethodNotAllowed) checkResponse(t, "status of disabled delete of manifest", resp, http.StatusMethodNotAllowed)
} }
func testManifestWithStorageError(t *testing.T, env *testEnv, imageName reference.Named, expectedStatusCode int, expectedErrorCode errcode.ErrorCode) {
tag := "latest"
tagRef, _ := reference.WithTag(imageName, tag)
manifestURL, err := env.builder.BuildManifestURL(tagRef)
if err != nil {
t.Fatalf("unexpected error getting manifest url: %v", err)
}
// -----------------------------
// Attempt to fetch the manifest
resp, err := http.Get(manifestURL)
if err != nil {
t.Fatalf("unexpected error getting manifest: %v", err)
}
defer resp.Body.Close()
checkResponse(t, "getting non-existent manifest", resp, expectedStatusCode)
checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, expectedErrorCode)
return
}
func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs { func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs {
tag := "thetag" tag := "thetag"
args := manifestArgs{imageName: imageName} args := manifestArgs{imageName: imageName}