mirror of https://github.com/minio/minio.git
More tests for web handlers (#2755)
* Return negative values of Total and Free in StorageInfo() when we fail to get disk info * Return consistent messages in web handlers when the server is not initialized
This commit is contained in:
parent
79e0c52fc2
commit
fc783f8407
|
@ -127,7 +127,7 @@ func (web *webAPIHandlers) StorageInfo(r *http.Request, args *GenericArgs, reply
|
|||
reply.UIVersion = miniobrowser.UIVersion
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Volume not found"}
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
reply.StorageInfo = objectAPI.StorageInfo()
|
||||
return nil
|
||||
|
@ -146,7 +146,7 @@ func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, rep
|
|||
reply.UIVersion = miniobrowser.UIVersion
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Volume not found"}
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
if err := objectAPI.MakeBucket(args.BucketName); err != nil {
|
||||
return &json2.Error{Message: err.Error()}
|
||||
|
@ -175,7 +175,7 @@ func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, re
|
|||
}
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Volume not found"}
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
buckets, err := objectAPI.ListBuckets()
|
||||
if err != nil {
|
||||
|
@ -227,7 +227,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r
|
|||
for {
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Volume not found"}
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, marker, "/", 1000)
|
||||
if err != nil {
|
||||
|
@ -269,7 +269,7 @@ func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs,
|
|||
reply.UIVersion = miniobrowser.UIVersion
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Volume not found"}
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
if err := objectAPI.DeleteObject(args.BucketName, args.ObjectName); err != nil {
|
||||
return &json2.Error{Message: err.Error()}
|
||||
|
@ -412,7 +412,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
writeWebErrorResponse(w, errors.New("Volume not found"))
|
||||
writeWebErrorResponse(w, errors.New("Server not initialized"))
|
||||
return
|
||||
}
|
||||
if _, err := objectAPI.PutObject(bucket, object, -1, r.Body, metadata); err != nil {
|
||||
|
@ -468,7 +468,7 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
writeWebErrorResponse(w, errors.New("Volume not found"))
|
||||
writeWebErrorResponse(w, errors.New("Server not initialized"))
|
||||
return
|
||||
}
|
||||
objInfo, err := objectAPI.GetObjectInfo(bucket, object)
|
||||
|
@ -594,16 +594,16 @@ func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolic
|
|||
if !isJWTReqAuthenticated(r) {
|
||||
return &json2.Error{Message: "Unauthorized request"}
|
||||
}
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
|
||||
bucketPolicy := policy.BucketPolicy(args.Policy)
|
||||
if !bucketPolicy.IsValidBucketPolicy() {
|
||||
return &json2.Error{Message: "Invalid policy " + args.Policy}
|
||||
}
|
||||
|
||||
objectAPI := web.ObjectAPI()
|
||||
if objectAPI == nil {
|
||||
return &json2.Error{Message: "Server not initialized"}
|
||||
}
|
||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||
if err != nil {
|
||||
return &json2.Error{Message: err.Error()}
|
||||
|
|
|
@ -23,8 +23,10 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
router "github.com/gorilla/mux"
|
||||
"github.com/minio/minio-go/pkg/policy"
|
||||
)
|
||||
|
||||
|
@ -742,7 +744,12 @@ func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE
|
|||
rec := httptest.NewRecorder()
|
||||
|
||||
bucketName := getRandomBucketName()
|
||||
if err = obj.MakeBucket(bucketName); err != nil {
|
||||
if err := obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
policyDoc := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"],\"Sid\":\"\"},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"],\"Sid\":\"\"}]}"
|
||||
if err := writeBucketPolicy(bucketName, obj, bytes.NewReader([]byte(policyDoc)), int64(len(policyDoc))); err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
|
@ -751,7 +758,7 @@ func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE
|
|||
prefix string
|
||||
expectedResult policy.BucketPolicy
|
||||
}{
|
||||
{bucketName, "", policy.BucketPolicyNone},
|
||||
{bucketName, "", policy.BucketPolicyReadOnly},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -846,3 +853,286 @@ func testWebSetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestWebCheckAuthorization - Test Authorization for all web handlers
|
||||
func TestWebCheckAuthorization(t *testing.T) {
|
||||
// Prepare XL backend
|
||||
obj, fsDirs, e := prepareXL()
|
||||
if e != nil {
|
||||
t.Fatalf("Initialization of object layer failed for XL setup: %s", e)
|
||||
}
|
||||
// Executing the object layer tests for XL.
|
||||
defer removeRoots(fsDirs)
|
||||
|
||||
// Register the API end points with XL/FS object layer.
|
||||
apiRouter := initTestWebRPCEndPoint(obj)
|
||||
// initialize the server and obtain the credentials and root.
|
||||
// credentials are necessary to sign the HTTP request.
|
||||
rootPath, e := newTestConfig("us-east-1")
|
||||
if e != nil {
|
||||
t.Fatalf("Init Test config failed")
|
||||
}
|
||||
// remove the root folder after the test ends.
|
||||
defer removeAll(rootPath)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
// Check if web rpc calls return unauthorized request with an incorrect token
|
||||
webRPCs := []string{"ServerInfo", "StorageInfo", "MakeBucket", "ListBuckets", "ListObjects", "RemoveObject", "GenerateAuth",
|
||||
"SetAuth", "GetAuth", "GetBucketPolicy", "SetBucketPolicy"}
|
||||
for _, rpcCall := range webRPCs {
|
||||
args := &GenericArgs{}
|
||||
reply := &WebGenericRep{}
|
||||
req, err := newTestWebRPCRequest("Web."+rpcCall, "Bearer fooauthorization", args)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %s: Failed to create HTTP request: <ERROR> %v", rpcCall, err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Test %s: Expected the response status to be 200, but instead found `%d`", rpcCall, rec.Code)
|
||||
}
|
||||
err = getTestWebRPCResponse(rec, &reply)
|
||||
if err == nil {
|
||||
t.Fatalf("Test %s: Should fail", rpcCall)
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), "Unauthorized request") {
|
||||
t.Fatalf("Test %s: should fail with Unauthorized request. Found error: %v", rpcCall, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test authorization of Web.Download
|
||||
req, err := http.NewRequest("GET", "/minio/download/bucket/object?token=wrongauth", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create upload request, %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp := string(rec.Body.Bytes())
|
||||
if !strings.Contains(resp, "Invalid token") {
|
||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
||||
}
|
||||
|
||||
// Test authorization of Web.Upload
|
||||
content := []byte("temporary file's content")
|
||||
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
||||
req.Header.Set("Authorization", "Bearer foo-authorization")
|
||||
req.Header.Set("Content-Length", strconv.Itoa(len(content)))
|
||||
req.Header.Set("x-amz-date", "20160814T114029Z")
|
||||
req.Header.Set("Accept", "*/*")
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(content))
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create upload request, %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp = string(rec.Body.Bytes())
|
||||
if !strings.Contains(resp, "Invalid token") {
|
||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWebObjectLayerNotReady - Test RPCs responses when disks are not ready
|
||||
func TestWebObjectLayerNotReady(t *testing.T) {
|
||||
webHandlers := &webAPIHandlers{
|
||||
ObjectAPI: func() ObjectLayer { return nil },
|
||||
}
|
||||
// Initialize router.
|
||||
apiRouter := router.NewRouter()
|
||||
registerWebRouter(apiRouter, webHandlers)
|
||||
|
||||
// initialize the server and obtain the credentials and root.
|
||||
// credentials are necessary to sign the HTTP request.
|
||||
rootPath, e := newTestConfig("us-east-1")
|
||||
if e != nil {
|
||||
t.Fatalf("Init Test config failed")
|
||||
}
|
||||
// remove the root folder after the test ends.
|
||||
defer removeAll(rootPath)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
credentials := serverConfig.GetCredential()
|
||||
authorization, e := getWebRPCToken(apiRouter, credentials.AccessKeyID, credentials.SecretAccessKey)
|
||||
if e != nil {
|
||||
t.Fatal("Cannot authenticate")
|
||||
}
|
||||
|
||||
// Check if web rpc calls return Server not initialized. ServerInfo, GenerateAuth,
|
||||
// SetAuth and GetAuth are not concerned
|
||||
webRPCs := []string{"StorageInfo", "MakeBucket", "ListBuckets", "ListObjects", "RemoveObject",
|
||||
"GetBucketPolicy", "SetBucketPolicy"}
|
||||
for _, rpcCall := range webRPCs {
|
||||
args := &GenericArgs{}
|
||||
reply := &WebGenericRep{}
|
||||
req, err := newTestWebRPCRequest("Web."+rpcCall, authorization, args)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %s: Failed to create HTTP request: <ERROR> %v", rpcCall, err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Test %s: Expected the response status to be 200, but instead found `%d`", rpcCall, rec.Code)
|
||||
}
|
||||
err = getTestWebRPCResponse(rec, &reply)
|
||||
if err == nil {
|
||||
t.Fatalf("Test %s: Should fail", rpcCall)
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), "Server not initialized") {
|
||||
t.Fatalf("Test %s: should fail with Unauthorized request. Found error: %v", rpcCall, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test authorization of Web.Download
|
||||
req, err := http.NewRequest("GET", "/minio/download/bucket/object?token="+authorization, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create upload request, %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp := string(rec.Body.Bytes())
|
||||
if !strings.Contains(resp, "We encountered an internal error, please try again.") {
|
||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
||||
}
|
||||
|
||||
// Test authorization of Web.Upload
|
||||
content := []byte("temporary file's content")
|
||||
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+authorization)
|
||||
req.Header.Set("Content-Length", strconv.Itoa(len(content)))
|
||||
req.Header.Set("x-amz-date", "20160814T114029Z")
|
||||
req.Header.Set("Accept", "*/*")
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(content))
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create upload request, %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp = string(rec.Body.Bytes())
|
||||
if !strings.Contains(resp, "We encountered an internal error, please try again.") {
|
||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWebObjectLayerFaultyDisks - Test Web RPC responses with faulty disks
|
||||
func TestWebObjectLayerFaultyDisks(t *testing.T) {
|
||||
// Prepare XL backend
|
||||
obj, fsDirs, e := prepareXL()
|
||||
if e != nil {
|
||||
t.Fatalf("Initialization of object layer failed for XL setup: %s", e)
|
||||
}
|
||||
// Executing the object layer tests for XL.
|
||||
defer removeRoots(fsDirs)
|
||||
|
||||
// Set faulty disks to XL backend
|
||||
xl := obj.(xlObjects)
|
||||
for i, d := range xl.storageDisks {
|
||||
xl.storageDisks[i] = newNaughtyDisk(d.(*posix), nil, errFaultyDisk)
|
||||
}
|
||||
|
||||
webHandlers := &webAPIHandlers{
|
||||
ObjectAPI: func() ObjectLayer { return obj },
|
||||
}
|
||||
// Initialize router.
|
||||
apiRouter := router.NewRouter()
|
||||
registerWebRouter(apiRouter, webHandlers)
|
||||
|
||||
// initialize the server and obtain the credentials and root.
|
||||
// credentials are necessary to sign the HTTP request.
|
||||
rootPath, e := newTestConfig("us-east-1")
|
||||
if e != nil {
|
||||
t.Fatalf("Init Test config failed")
|
||||
}
|
||||
// remove the root folder after the test ends.
|
||||
defer removeAll(rootPath)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
credentials := serverConfig.GetCredential()
|
||||
authorization, e := getWebRPCToken(apiRouter, credentials.AccessKeyID, credentials.SecretAccessKey)
|
||||
if e != nil {
|
||||
t.Fatal("Cannot authenticate")
|
||||
}
|
||||
|
||||
// Check if web rpc calls return errors with faulty disks. ServerInfo, GenerateAuth, SetAuth, GetAuth are not concerned
|
||||
webRPCs := []string{"MakeBucket", "ListBuckets", "ListObjects", "RemoveObject",
|
||||
"GetBucketPolicy", "SetBucketPolicy"}
|
||||
|
||||
for _, rpcCall := range webRPCs {
|
||||
args := &GenericArgs{}
|
||||
reply := &WebGenericRep{}
|
||||
req, err := newTestWebRPCRequest("Web."+rpcCall, authorization, args)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %s: Failed to create HTTP request: <ERROR> %v", rpcCall, err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Test %s: Expected the response status to be 200, but instead found `%d`", rpcCall, rec.Code)
|
||||
}
|
||||
err = getTestWebRPCResponse(rec, &reply)
|
||||
if err == nil {
|
||||
t.Errorf("Test %s: Should fail", rpcCall)
|
||||
}
|
||||
}
|
||||
|
||||
// Test Web.StorageInfo
|
||||
storageInfoRequest := GenericArgs{}
|
||||
storageInfoReply := &StorageInfoRep{}
|
||||
req, err := newTestWebRPCRequest("Web.StorageInfo", authorization, storageInfoRequest)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create HTTP request: <ERROR> %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
err = getTestWebRPCResponse(rec, &storageInfoReply)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed %v", err)
|
||||
}
|
||||
if storageInfoReply.StorageInfo.Total != -1 || storageInfoReply.StorageInfo.Free != -1 {
|
||||
t.Fatalf("Should get negative values of Total and Free since disks are faulty ")
|
||||
}
|
||||
|
||||
// Test authorization of Web.Download
|
||||
req, err = http.NewRequest("GET", "/minio/download/bucket/object?token="+authorization, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create upload request, %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp := string(rec.Body.Bytes())
|
||||
if !strings.Contains(resp, "We encountered an internal error, please try again.") {
|
||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
||||
}
|
||||
|
||||
// Test authorization of Web.Upload
|
||||
content := []byte("temporary file's content")
|
||||
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+authorization)
|
||||
req.Header.Set("Content-Length", strconv.Itoa(len(content)))
|
||||
req.Header.Set("x-amz-date", "20160814T114029Z")
|
||||
req.Header.Set("Accept", "*/*")
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(content))
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create upload request, %v", err)
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp = string(rec.Body.Bytes())
|
||||
if !strings.Contains(resp, "We encountered an internal error, please try again.") {
|
||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,6 +224,12 @@ func (xl xlObjects) StorageInfo() StorageInfo {
|
|||
// Sort so that the first element is the smallest.
|
||||
sort.Sort(byDiskTotal(disksInfo))
|
||||
|
||||
if len(disksInfo) == 0 {
|
||||
return StorageInfo{
|
||||
Total: -1,
|
||||
Free: -1,
|
||||
}
|
||||
}
|
||||
// Return calculated storage info, choose the lowest Total and
|
||||
// Free as the total aggregated values. Total capacity is always
|
||||
// the multiple of smallest disk among the disk list.
|
||||
|
|
Loading…
Reference in New Issue