2016-12-02 16:57:41 -08:00
/*
Copyright 2016 The Rook Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package api
import (
2017-02-03 13:16:36 -08:00
"bytes"
2016-12-02 16:57:41 -08:00
"encoding/json"
2017-02-03 13:16:36 -08:00
"fmt"
2016-12-02 16:57:41 -08:00
"io/ioutil"
"net/http"
"net/http/httptest"
2017-02-03 13:16:36 -08:00
"os"
2017-06-14 16:07:36 -07:00
"path/filepath"
2017-09-01 12:52:14 -07:00
"strings"
2016-12-02 16:57:41 -08:00
"testing"
2017-10-05 10:00:19 -07:00
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
2016-12-02 16:57:41 -08:00
"github.com/rook/rook/pkg/clusterd"
"github.com/rook/rook/pkg/model"
2017-02-03 13:16:36 -08:00
testexec "github.com/rook/rook/pkg/util/exec/test"
2016-12-02 16:57:41 -08:00
"github.com/stretchr/testify/assert"
2017-10-05 10:00:19 -07:00
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2016-12-02 16:57:41 -08:00
)
func TestCreateObjectStoreHandler ( t * testing . T ) {
2017-10-05 10:00:19 -07:00
createdZone := false
poolInit := true
executor := & testexec . MockExecutor {
MockExecuteCommandWithOutputFile : func ( debug bool , actionName string , command string , outFileArg string , args ... string ) ( string , error ) {
//logger.Infof("Command: %s %v", command, args)
if args [ 0 ] == "auth" {
return `{"key":"mykey"}` , nil
}
if args [ 1 ] == "pool" {
if args [ 2 ] == "create" {
return "" , nil
}
if args [ 2 ] == "set" && args [ 4 ] == "size" {
assert . Equal ( t , "1" , args [ 5 ])
return "" , nil
}
if args [ 2 ] == "application" {
poolInit = true
return "" , nil
}
}
return "" , fmt . Errorf ( "unexpected command '%s'" , args [ 0 ])
},
MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName string , command string , args ... string ) ( string , error ) {
//logger.Infof("Command: %s %v", command, args)
if args [ 0 ] == "realm" && args [ 1 ] == "create" {
return `{"id":"realm"}` , nil
}
if args [ 0 ] == "zonegroup" && args [ 1 ] == "create" {
return `{"id":"group"}` , nil
}
if args [ 0 ] == "zone" && args [ 1 ] == "create" {
createdZone = true
return `{"id":"myzone"}` , nil
}
if args [ 0 ] == "period" && args [ 1 ] == "update" {
return "" , nil
}
return "" , fmt . Errorf ( "unexpected combined output command '%s'" , args [ 0 ])
},
}
2016-12-02 16:57:41 -08:00
w := httptest . NewRecorder ()
2017-10-05 10:00:19 -07:00
h := newTestHandler ( & clusterd . Context { Executor : executor })
2017-09-14 12:26:42 -07:00
// Valid parameters return a 200
2017-10-05 10:00:19 -07:00
req , err := http . NewRequest ( "POST" , "http://10.0.0.100/objectstore" , strings . NewReader ( `{"name": "default","dataConfig":{"replicatedConfig":{"size":1}},"metadataConfig":{"replicatedConfig":{"size":1}},"gateway": {"port":1234}}` ))
2017-09-14 12:26:42 -07:00
assert . Nil ( t , err )
2016-12-02 16:57:41 -08:00
h . CreateObjectStore ( w , req )
2017-09-14 12:26:42 -07:00
assert . Equal ( t , http . StatusOK , w . Code )
2017-10-05 10:00:19 -07:00
assert . True ( t , createdZone )
assert . True ( t , poolInit )
2017-09-14 12:26:42 -07:00
// Invalid parameters return a 400
req , err = http . NewRequest ( "POST" , "http://10.0.0.100/objectstore" , strings . NewReader ( `{"name": "default"}` ))
assert . Nil ( t , err )
h . CreateObjectStore ( w , req )
assert . Equal ( t , http . StatusBadRequest , w . Code )
2016-12-02 16:57:41 -08:00
}
func TestRemoveObjectStoreHandler ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "DELETE" , "http://10.0.0.100/objectstore/mystore" , nil )
2016-12-02 16:57:41 -08:00
if err != nil {
logger . Fatal ( err )
}
2017-09-11 14:56:10 -07:00
configDir , _ := ioutil . TempDir ( "" , "" )
defer os . RemoveAll ( configDir )
2016-12-02 16:57:41 -08:00
2017-10-05 10:00:19 -07:00
// call RemoveObjectStore handler and verify the response is 202 Accepted
context := & clusterd . Context {}
2016-12-02 16:57:41 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2016-12-02 16:57:41 -08:00
h . RemoveObjectStore ( w , req )
2017-09-14 12:26:42 -07:00
assert . Equal ( t , http . StatusOK , w . Code )
2016-12-02 16:57:41 -08:00
}
func TestGetObjectStoreConnectionInfoHandler ( t * testing . T ) {
2017-10-05 10:00:19 -07:00
context := & clusterd . Context {}
req , err := http . NewRequest ( "GET" , "http://10.0.0.100/objectstore/myinst/connectioninfo?name=myinst" , nil )
require . Nil ( t , err )
2016-12-02 16:57:41 -08:00
// before RGW has been installed or any user accounts have been created, the handler will return 404 not found
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-10-05 10:00:19 -07:00
// get the connection info
r := newRouter ( h . GetRoutes ())
r . ServeHTTP ( w , req )
2016-12-02 16:57:41 -08:00
assert . Equal ( t , http . StatusNotFound , w . Code )
2017-10-05 10:00:19 -07:00
// now simulate the rgw service with the kubernetes service
ns := "default"
svc := & v1 . Service {
ObjectMeta : metav1 . ObjectMeta {
Name : "rook-ceph-rgw-myinst" ,
Namespace : ns ,
},
Spec : v1 . ServiceSpec {
Ports : [] v1 . ServicePort {
{
Name : "http" ,
Port : 80 ,
TargetPort : intstr . FromInt ( int ( 80 )),
Protocol : v1 . ProtocolTCP ,
},
},
},
}
_ , err = context . Clientset . CoreV1 (). Services ( ns ). Create ( svc )
assert . Nil ( t , err )
2016-12-02 16:57:41 -08:00
w = httptest . NewRecorder ()
2017-10-05 10:00:19 -07:00
r . ServeHTTP ( w , req )
2016-12-02 16:57:41 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
2017-02-07 08:38:36 -08:00
expectedRespObj := model . ObjectStoreConnectInfo {
2017-10-05 10:00:19 -07:00
Host : "rook-ceph-rgw-myinst" ,
Ports : [] int32 { 80 },
2016-12-02 16:57:41 -08:00
}
// unmarshal the http response to get the actual object and compare it to the expected object
2017-02-07 08:38:36 -08:00
var actualResultObj model . ObjectStoreConnectInfo
2016-12-02 16:57:41 -08:00
bodyBytes , _ := ioutil . ReadAll ( w . Body )
json . Unmarshal ( bodyBytes , & actualResultObj )
assert . Equal ( t , expectedRespObj , actualResultObj )
}
2017-02-03 13:16:36 -08:00
func TestListUsers ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "GET" , "http://10.0.0.100/objectstore/default/users" , nil )
2017-02-03 13:16:36 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( runner func ( args ... string ) ( string , error )) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
return runner ( args ... )
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-02-03 13:16:36 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-02-03 13:16:36 -08:00
h . ListUsers ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedListArgs := [] string { "user" , "list" }
expectedInfoArgs := [] string { "user" , "info" , "--uid" }
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
// Empty list
w := runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedListArgs )
2017-02-03 13:16:36 -08:00
return "[]" , nil
})
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , "[]" , w . Body . String ())
// One item
w = runTest ( func ( args ... string ) ( string , error ) {
2017-06-14 16:07:36 -07:00
if args [ 1 ] == "list" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedListArgs )
2017-02-03 13:16:36 -08:00
return `["testuser"]` , nil
}
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , append ( expectedInfoArgs , "testuser" ))
2017-02-03 13:16:36 -08:00
return `{"user_id":"testuser","display_name":"Test User","email":"testuser@example.com","keys":[{"access_key":"somekey","secret_key":"somesecret","user":"testuser"}]}` , nil
})
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `[{"userId":"testuser","displayName":"Test User","email":"testuser@example.com","accessKey":"somekey","secretKey":"somesecret"}]` , w . Body . String ())
// Two items
first := true
w = runTest ( func ( args ... string ) ( string , error ) {
2017-06-14 16:07:36 -07:00
if args [ 1 ] == "list" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedListArgs )
2017-02-03 13:16:36 -08:00
return `["testuser","otheruser"]` , nil
}
if first {
first = false
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , append ( expectedInfoArgs , "testuser" ))
2017-02-03 13:16:36 -08:00
return `{"user_id":"testuser","display_name":"Test User","email":"testuser@example.com","keys":[]}` , nil
}
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , append ( expectedInfoArgs , "otheruser" ))
2017-02-03 13:16:36 -08:00
return `{"user_id":"otheruser","display_name":"Other User","keys":[{"access_key":"otherkey","secret_key":"othersecret","user":"otheruser"},{"access_key":"we","secret_key":"foo","user":"bar"}]}` , nil
})
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `[{"userId":"testuser","displayName":"Test User","email":"testuser@example.com","accessKey":null,"secretKey":null},{"userId":"otheruser","displayName":"Other User","email":"","accessKey":"otherkey","secretKey":"othersecret"}]` , w . Body . String ())
// Error getting users list
w = runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedListArgs )
2017-02-03 13:16:36 -08:00
return "" , fmt . Errorf ( "some error" )
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Error getting user
w = runTest ( func ( args ... string ) ( string , error ) {
if args [ 4 ] == "list" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedListArgs )
2017-02-03 13:16:36 -08:00
return `["testuser"]` , nil
}
return "" , fmt . Errorf ( "some error" )
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// User list no parseable
w = runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedListArgs )
2017-02-03 13:16:36 -08:00
return "[bad ,format" , nil
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
}
func TestGetUser ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "GET" , "http://10.0.0.100/objectstore/default/users/someuser" , nil )
2017-02-03 13:16:36 -08:00
if err != nil {
logger . Fatal ( err )
}
2017-06-06 12:58:09 -07:00
configDir , _ := ioutil . TempDir ( "" , "" )
defer os . RemoveAll ( configDir )
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
runTest := func ( s string , e error , expectedArgs ... string ) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedArgs )
2017-02-03 13:16:36 -08:00
return s , e
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-02-03 13:16:36 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-02-07 08:38:36 -08:00
r := newRouter ( h . GetRoutes ())
2017-02-03 13:16:36 -08:00
r . ServeHTTP ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedArgs := [] string { "user" , "info" , "--uid" , "someuser" }
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
// Error getting user
2017-06-14 16:07:36 -07:00
w := runTest ( "" , fmt . Errorf ( "some error" ), expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Get user with no keys
2017-06-14 16:07:36 -07:00
w = runTest ( `{"user_id":"testuser","display_name":"Test User","email":"testuser@example.com","keys":[]}` , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `{"userId":"testuser","displayName":"Test User","email":"testuser@example.com","accessKey":null,"secretKey":null}` , w . Body . String ())
// Get user with one key
2017-06-14 16:07:36 -07:00
w = runTest ( `{"user_id":"testuser","display_name":"Test User","email":"testuser@example.com","keys":[{"access_key":"otherkey","secret_key":"othersecret","user":"otheruser"},{"access_key":"we","secret_key":"foo","user":"bar"}]}` , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `{"userId":"testuser","displayName":"Test User","email":"testuser@example.com","accessKey":"otherkey","secretKey":"othersecret"}` , w . Body . String ())
// Get user with multiple keys
2017-06-14 16:07:36 -07:00
w = runTest ( `{"user_id":"testuser","display_name":"Test User","email":"testuser@example.com","keys":[{"access_key":"we","secret_key":"foo","user":"bar"}]}` , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `{"userId":"testuser","displayName":"Test User","email":"testuser@example.com","accessKey":"we","secretKey":"foo"}` , w . Body . String ())
// Get user that does not exist
2017-06-14 16:07:36 -07:00
w = runTest ( "could not fetch user info: no user info saved" , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusNotFound , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Unable to parse user json
2017-06-14 16:07:36 -07:00
w = runTest ( "[bad, format" , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
}
func TestCreateUser ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "POST" , "http://10.0.0.100/objectstore/default/users" , nil )
2017-02-03 13:16:36 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( body string , s string , e error , expectedArgs ... string ) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedArgs )
2017-02-03 13:16:36 -08:00
return s , e
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-02-03 13:16:36 -08:00
req . Body = ioutil . NopCloser ( bytes . NewBufferString ( body ))
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-02-07 08:38:36 -08:00
r := newRouter ( h . GetRoutes ())
2017-02-03 13:16:36 -08:00
r . ServeHTTP ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedDisplayNameArgs := [] string { "user" , "create" , "--uid" , "foo" , "--display-name" , "the foo" }
expectedDisplayNameAndEmailArgs := [] string { "user" , "create" , "--uid" , "foo" , "--display-name" , "the foo" , "--email" , "test@example.com" }
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
// Empty body
w := runTest ( "" , "" , nil , "" , "" )
assert . Equal ( t , http . StatusBadRequest , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// User id empty
w = runTest ( "{}" , "" , nil , "" , "" )
assert . Equal ( t , http . StatusUnprocessableEntity , w . Code )
assert . Equal ( t , "userId cannot be empty" , w . Body . String ())
// No display name
w = runTest ( `{"userId":"foo"}` , "" , nil , "" , "" )
assert . Equal ( t , http . StatusUnprocessableEntity , w . Code )
assert . Equal ( t , "displayName is required" , w . Body . String ())
// Error creating
2017-06-14 16:07:36 -07:00
w = runTest ( `{"userId":"foo","displayName":"the foo"}` , "" , fmt . Errorf ( "some error" ), expectedDisplayNameArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// UserID already exists
2017-06-14 16:07:36 -07:00
w = runTest ( `{"userId":"foo","displayName":"the foo"}` , "could not create user: unable to create user, user: foo exists" , nil , expectedDisplayNameArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusUnprocessableEntity , w . Code )
assert . Equal ( t , "user already exists" , w . Body . String ())
// Email already exists
2017-06-14 16:07:36 -07:00
w = runTest ( `{"userId":"foo","displayName":"the foo","email":"test@example.com"}` , "could not create user: unable to create user, email: test@example.com is the email address an existing user" , nil , expectedDisplayNameAndEmailArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusUnprocessableEntity , w . Code )
assert . Equal ( t , "email already in use" , w . Body . String ())
// Success without email
2017-06-14 16:07:36 -07:00
w = runTest ( `{"userId":"foo","displayName":"the foo"}` , `{"user_id":"foo","display_name":"the foo","keys":[{"secret_key":"sk","access_key":"ak"}]}` , nil , expectedDisplayNameArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusCreated , w . Code )
assert . Equal ( t , `{"userId":"foo","displayName":"the foo","email":"","accessKey":"ak","secretKey":"sk"}` , w . Body . String ())
// Success with email
2017-06-14 16:07:36 -07:00
w = runTest ( `{"userId":"foo","displayName":"the foo","email":"test@example.com"}` , `{"user_id":"foo","display_name":"the foo","email":"test@example.com","keys":[{"secret_key":"sk","access_key":"ak"}]}` , nil , expectedDisplayNameAndEmailArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusCreated , w . Code )
assert . Equal ( t , `{"userId":"foo","displayName":"the foo","email":"test@example.com","accessKey":"ak","secretKey":"sk"}` , w . Body . String ())
}
func TestUpdateUser ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "PUT" , "http://10.0.0.100/objectstore/default/users/foo" , nil )
2017-02-03 13:16:36 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( body string , s string , e error , expectedArgs ... string ) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedArgs )
2017-02-03 13:16:36 -08:00
return s , e
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-02-03 13:16:36 -08:00
req . Body = ioutil . NopCloser ( bytes . NewBufferString ( body ))
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-02-07 08:38:36 -08:00
r := newRouter ( h . GetRoutes ())
2017-02-03 13:16:36 -08:00
r . ServeHTTP ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedArgs := [] string { "user" , "modify" , "--uid" , "foo" }
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
// Empty body
w := runTest ( "" , "" , nil , "" , "" )
assert . Equal ( t , http . StatusBadRequest , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Error updating user
2017-06-14 16:07:36 -07:00
w = runTest ( "{}" , "" , fmt . Errorf ( "some error" ), expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// User not found
2017-06-14 16:07:36 -07:00
w = runTest ( "{}" , "could not modify user: unable to modify user, user not found" , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusNotFound , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Success with display name
2017-09-11 14:56:10 -07:00
expectedArgs = [] string { "user" , "modify" , "--uid" , "foo" , "--display-name" , "different name" }
2017-06-14 16:07:36 -07:00
w = runTest (
`{"displayName":"different name"}` ,
`{"user_id":"foo","display_name":"different name","email":"test@example.com","keys":[{"secret_key":"sk","access_key":"ak"},{"secret_key":"ok","access_key":"bk"}]}` ,
nil ,
2017-09-11 14:56:10 -07:00
expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `{"userId":"foo","displayName":"different name","email":"test@example.com","accessKey":"ak","secretKey":"sk"}` , w . Body . String ())
// Success with email
2017-09-11 14:56:10 -07:00
expectedArgs = [] string { "user" , "modify" , "--uid" , "foo" , "--email" , "different@example.com" }
2017-06-14 16:07:36 -07:00
w = runTest (
`{"email":"different@example.com"}` ,
`{"user_id":"foo","display_name":"old name","email":"different@example.com","keys":[{"secret_key":"sk","access_key":"ak"},{"secret_key":"ok","access_key":"bk"}]}` ,
nil ,
2017-09-11 14:56:10 -07:00
expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `{"userId":"foo","displayName":"old name","email":"different@example.com","accessKey":"ak","secretKey":"sk"}` , w . Body . String ())
// Success with display name and email
2017-09-11 14:56:10 -07:00
expectedArgs = [] string { "user" , "modify" , "--uid" , "foo" , "--display-name" , "different name" , "--email" , "different@example.com" }
2017-06-14 16:07:36 -07:00
w = runTest (
`{"displayName":"different name","email":"different@example.com"}` ,
`{"user_id":"foo","display_name":"different name","email":"different@example.com","keys":[{"secret_key":"sk","access_key":"ak"},{"secret_key":"ok","access_key":"bk"}]}` ,
nil ,
2017-09-11 14:56:10 -07:00
expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `{"userId":"foo","displayName":"different name","email":"different@example.com","accessKey":"ak","secretKey":"sk"}` , w . Body . String ())
}
func TestDeleteUser ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "DELETE" , "http://10.0.0.100/objectstore/default/users/foo" , nil )
2017-02-03 13:16:36 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( s string , e error , expectedArgs ... string ) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedArgs )
2017-02-03 13:16:36 -08:00
return s , e
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-02-03 13:16:36 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-02-07 08:38:36 -08:00
r := newRouter ( h . GetRoutes ())
2017-02-03 13:16:36 -08:00
r . ServeHTTP ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedArgs := [] string { "user" , "rm" , "--uid" , "foo" }
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
// Some error
2017-06-14 16:07:36 -07:00
w := runTest ( "" , fmt . Errorf ( "some error" ), expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// User not found
2017-06-14 16:07:36 -07:00
w = runTest ( "unable to remove user, user does not exist" , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusNotFound , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Success
2017-06-14 16:07:36 -07:00
w = runTest ( "" , nil , expectedArgs ... )
2017-02-03 13:16:36 -08:00
assert . Equal ( t , http . StatusNoContent , w . Code )
assert . Equal ( t , "" , w . Body . String ())
}
func TestListBuckets ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "GET" , "http://10.0.0.100/objectstore/default/buckets" , nil )
2017-02-03 13:16:36 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( runner func ( args ... string ) ( string , error )) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
return runner ( args ... )
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-02-03 13:16:36 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-03-07 14:38:55 -08:00
h . ListBuckets ( w , req )
2017-02-03 13:16:36 -08:00
return w
}
2017-09-11 14:56:10 -07:00
expectedStatsArgs := [] string { "bucket" , "stats" }
expectedMetadataArgs := [] string { "metadata" , "get" , "bucket:foo" }
2017-06-14 16:07:36 -07:00
2017-02-03 13:16:36 -08:00
// List error
w := runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return "" , fmt . Errorf ( "some error" )
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Empty list
w = runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return "[]" , nil
})
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , "[]" , w . Body . String ())
// Bad list format
w = runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return "[bad, format" , nil
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
oneStat := `[{"bucket":"foo","usage":{"pool1":{"size":4,"num_objects":2},"pool2":{"size":5,"num_objects":4}}}]`
// error getting metadata
first := true
w = runTest ( func ( args ... string ) ( string , error ) {
if first {
first = false
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return oneStat , nil
}
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-02-03 13:16:36 -08:00
return "" , fmt . Errorf ( "some error" )
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Bad metadata format
first = true
w = runTest ( func ( args ... string ) ( string , error ) {
if first {
first = false
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return oneStat , nil
}
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-02-03 13:16:36 -08:00
return "[bad, format" , nil
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Bad date format
first = true
w = runTest ( func ( args ... string ) ( string , error ) {
if first {
first = false
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return oneStat , nil
}
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-02-03 13:16:36 -08:00
return `{"data":{"owner":"bob","creation_time":"fds"}}` , nil
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Success
first = true
w = runTest ( func ( args ... string ) ( string , error ) {
if first {
first = false
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return oneStat , nil
}
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-02-03 13:16:36 -08:00
return `{"data":{"owner":"bob","creation_time":"2016-08-05 16:23:34.343343Z"}}` , nil
})
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , `[{"name":"foo","owner":"bob","createdAt":"2016-08-05T16:23:34.343343Z","size":9,"numberOfObjects":6}]` , w . Body . String ())
// Two buckets
2017-02-13 13:38:37 -08:00
first = true
2017-02-03 13:16:36 -08:00
w = runTest ( func ( args ... string ) ( string , error ) {
2017-02-13 13:38:37 -08:00
if first {
// Expect the stats call
first = false
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-02-03 13:16:36 -08:00
return `[{"bucket":"foo","usage":{"pool1":{"size":4,"num_objects":2}}},{"bucket":"bar","usage":{"pool2":{"size":5,"num_objects":4}}}]` , nil
2017-02-13 13:38:37 -08:00
} else {
// Expect the bucket metadata calls
2017-09-11 14:56:10 -07:00
if containsArg ( args , "bucket:foo" ) {
2017-02-13 13:38:37 -08:00
return `{"data":{"owner":"bob","creation_time":"2016-08-05 16:23:34.343343Z"}}` , nil
2017-09-11 14:56:10 -07:00
} else if containsArg ( args , "bucket:bar" ) {
2017-02-13 13:38:37 -08:00
return `{"data":{"owner":"bill","creation_time":"2016-08-05 18:31:22.445343Z"}}` , nil
} else {
2017-09-11 14:56:10 -07:00
assert . Fail ( t , fmt . Sprintf ( "Wasn't foo or bar: %+v" , args ))
2017-02-13 13:38:37 -08:00
}
2017-02-03 13:16:36 -08:00
}
assert . Fail ( t , "Shouldn't return more than 3 times" )
return "" , fmt . Errorf ( "Shouldn't return more than 3 times" )
})
assert . Equal ( t , http . StatusOK , w . Code )
2017-02-09 16:20:52 -08:00
assert . Equal ( t , `[{"name":"bar","owner":"bill","createdAt":"2016-08-05T18:31:22.445343Z","size":5,"numberOfObjects":4},{"name":"foo","owner":"bob","createdAt":"2016-08-05T16:23:34.343343Z","size":4,"numberOfObjects":2}]` , w . Body . String ())
2017-02-03 13:16:36 -08:00
}
2017-03-07 14:38:55 -08:00
2017-09-11 14:56:10 -07:00
func checkArgs ( t * testing . T , args , desired [] string ) {
// check that all hte desired args are found in order in the list of args
start := indexIn ( args , desired [ 0 ])
for i , d := range desired {
assert . Equal ( t , args [( start + i )], d , fmt . Sprintf ( "%s not found at position %d in %v" , d , ( start + i ), args ))
}
}
func indexIn ( values [] string , desired string ) int {
for i , val := range values {
if val == desired {
return i
}
}
return - 1
}
func containsArg ( values [] string , desired string ) bool {
for _ , val := range values {
if val == desired {
return true
}
}
return false
}
2017-03-07 14:38:55 -08:00
func TestGetBucket ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "GET" , "http://10.0.0.100/objectstore/default/buckets/test" , nil )
2017-03-07 14:38:55 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( runner func ( args ... string ) ( string , error )) * httptest . ResponseRecorder {
2017-08-07 10:58:52 -07:00
executor := & testexec . MockExecutor { MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
return runner ( args ... )
}}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-03-07 14:38:55 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-03-07 14:38:55 -08:00
r := newRouter ( h . GetRoutes ())
r . ServeHTTP ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedStatsArgs := [] string { "bucket" , "stats" , "--bucket" , "test" }
expectedMetadataArgs := [] string { "metadata" , "get" , "bucket:test" }
2017-06-14 16:07:36 -07:00
2017-03-07 14:38:55 -08:00
// Stats fails
w := runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return "" , fmt . Errorf ( "some error" )
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// stats not found
w = runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return `2017-03-07 09:07:30.868797 c269240 0 could not get bucket info for bucket=tesdsft
2017-06-14 16:07:36 -07:00
2017-03-07 09:07:30.868797 c269240 0 could not get bucket info for bucket=tesdsft` , nil
2017-03-07 14:38:55 -08:00
})
assert . Equal ( t , http . StatusNotFound , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Error parsing stats
w = runTest ( func ( args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return "{" , nil
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// metadata fail
w = runTest ( func ( args ... string ) ( string , error ) {
2017-06-14 16:07:36 -07:00
if args [ 1 ] == "stats" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return "{}" , nil
} else {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-03-07 14:38:55 -08:00
return "" , fmt . Errorf ( "some error" )
}
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// metadata not found
w = runTest ( func ( args ... string ) ( string , error ) {
2017-06-14 16:07:36 -07:00
if args [ 1 ] == "stats" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return "{}" , nil
} else {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-03-07 14:38:55 -08:00
return "ERROR: can't get key: (2) No such file or directory" , nil
}
})
assert . Equal ( t , http . StatusNotFound , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// metadata parse fail
w = runTest ( func ( args ... string ) ( string , error ) {
2017-06-14 16:07:36 -07:00
if args [ 1 ] == "stats" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return "{}" , nil
} else {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-03-07 14:38:55 -08:00
return "{" , nil
}
})
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Success
w = runTest ( func ( args ... string ) ( string , error ) {
2017-06-14 16:07:36 -07:00
if args [ 1 ] == "stats" {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedStatsArgs )
2017-03-07 14:38:55 -08:00
return `{"bucket":"test","usage":{"pool2":{"size":5,"num_objects":4}}}` , nil
} else {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedMetadataArgs )
2017-03-07 14:38:55 -08:00
return `{"data":{"owner":"bill","creation_time":"2016-08-05 18:31:22.445343Z"}}` , nil
}
})
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , "{\"name\":\"test\",\"owner\":\"bill\",\"createdAt\":\"2016-08-05T18:31:22.445343Z\",\"size\":5,\"numberOfObjects\":4}" , w . Body . String ())
}
func TestBucketDelete ( t * testing . T ) {
2017-09-14 16:11:20 -07:00
req , err := http . NewRequest ( "DELETE" , "http://10.0.0.100/objectstore/default/buckets/test" , nil )
2017-03-07 14:38:55 -08:00
if err != nil {
logger . Fatal ( err )
}
runTest := func ( s string , e error , expectedArgs ... string ) * httptest . ResponseRecorder {
2017-06-14 16:07:36 -07:00
executor := & testexec . MockExecutor {
2017-08-07 10:58:52 -07:00
MockExecuteCommandWithCombinedOutput : func ( debug bool , actionName , command string , args ... string ) ( string , error ) {
2017-09-11 14:56:10 -07:00
checkArgs ( t , args , expectedArgs )
2017-06-14 16:07:36 -07:00
return s , e
},
}
2017-10-05 10:00:19 -07:00
context := & clusterd . Context { Executor : executor }
2017-06-14 16:07:36 -07:00
2017-03-07 14:38:55 -08:00
w := httptest . NewRecorder ()
2017-06-02 13:44:54 -07:00
h := newTestHandler ( context )
2017-03-07 14:38:55 -08:00
r := newRouter ( h . GetRoutes ())
r . ServeHTTP ( w , req )
return w
}
2017-09-11 14:56:10 -07:00
expectedArgs := [] string { "bucket" , "rm" , "--bucket" , "test" }
2017-06-14 16:07:36 -07:00
2017-03-07 14:38:55 -08:00
// errors
2017-06-14 16:07:36 -07:00
w := runTest ( "" , fmt . Errorf ( "some error" ), expectedArgs ... )
2017-03-07 14:38:55 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Not found
w = runTest ( `2017-03-07 09:36:45.605774 c081240 0 could not get bucket info for bucket=tesdsft
2017-06-14 16:07:36 -07:00
2017-03-07 09:36:45.605774 c081240 0 could not get bucket info for bucket=tesdsft` , nil , expectedArgs ... )
2017-03-07 14:38:55 -08:00
assert . Equal ( t , http . StatusNotFound , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Not found
2017-06-14 16:07:36 -07:00
w = runTest ( "unexpected content" , nil , expectedArgs ... )
2017-03-07 14:38:55 -08:00
assert . Equal ( t , http . StatusInternalServerError , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Succeeds
2017-06-14 16:07:36 -07:00
w = runTest ( "" , nil , expectedArgs ... )
2017-03-07 14:38:55 -08:00
assert . Equal ( t , http . StatusNoContent , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// not Purge
2017-09-14 16:11:20 -07:00
req , err = http . NewRequest ( "DELETE" , "http://10.0.0.100/objectstore/default/buckets/test?purge=false" , nil )
2017-03-07 14:38:55 -08:00
if err != nil {
logger . Fatal ( err )
}
2017-06-14 16:07:36 -07:00
w = runTest ( "" , nil , expectedArgs ... )
2017-03-07 14:38:55 -08:00
assert . Equal ( t , http . StatusNoContent , w . Code )
assert . Equal ( t , "" , w . Body . String ())
// Purge
2017-09-11 14:56:10 -07:00
expectedArgs = [] string { "bucket" , "rm" , "--bucket" , "test" , "--purge-objects" }
2017-09-14 16:11:20 -07:00
req , err = http . NewRequest ( "DELETE" , "http://10.0.0.100/objectstore/default/buckets/test?purge=true" , nil )
2017-03-07 14:38:55 -08:00
if err != nil {
logger . Fatal ( err )
}
2017-06-14 16:07:36 -07:00
w = runTest ( "" , nil , expectedArgs ... )
2017-03-07 14:38:55 -08:00
assert . Equal ( t , http . StatusNoContent , w . Code )
assert . Equal ( t , "" , w . Body . String ())
}
2017-06-14 16:07:36 -07:00
func getConfigSubDir ( configDir string ) string {
return filepath . Join ( configDir , "rookcluster" )
}
func getExectedConfigArg ( configSubDir string ) string {
return fmt . Sprintf ( "--conf=%s/rookcluster.config" , configSubDir )
}
func getExpectedKeyringArg ( configSubDir string ) string {
return fmt . Sprintf ( "--keyring=%s/client.admin.keyring" , configSubDir )
}