tests: Add tests for browser peer rpc. Fixes #3062 (#3189)

This commit is contained in:
Harshavardhana 2016-11-07 11:43:35 -08:00 committed by GitHub
parent 286a8924fd
commit 33c771bb3e
7 changed files with 173 additions and 23 deletions

View File

@ -1,5 +1,5 @@
/*
* Minio Cloud Storage, (C) 2014-2016 Minio, Inc.
* Minio Cloud Storage, (C) 2016 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,7 +22,9 @@ import (
"time"
)
func (br *browserAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
// Login handler implements JWT login token generator, which upon login request
// along with username and password is generated.
func (br *browserPeerAPIHandlers) LoginHandler(args *RPCLoginArgs, reply *RPCLoginReply) error {
jwt, err := newJWT(defaultInterNodeJWTExpiry)
if err != nil {
return err
@ -56,7 +58,7 @@ type SetAuthPeerArgs struct {
// will be forced to re-establish connections. Connections will be
// re-established only when the sending client has also updated its
// credentials.
func (br *browserAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *GenericReply) error {
func (br *browserPeerAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *GenericReply) error {
// Check auth
if !isRPCTokenValid(args.Token) {
return errInvalidToken
@ -83,8 +85,7 @@ func updateCredsOnPeers(creds credential) map[string]error {
errs := make([]error, len(peers))
var wg sync.WaitGroup
// Launch go routines to send request to each peer in
// parallel.
// Launch go routines to send request to each peer in parallel.
for ix := range peers {
wg.Add(1)
go func(ix int) {
@ -103,7 +104,7 @@ func updateCredsOnPeers(creds credential) map[string]error {
secretKey: serverConfig.GetCredential().SecretAccessKey,
address: peers[ix],
secureConn: isSSL(),
path: path.Join(reservedBucket, browserPath),
path: path.Join(reservedBucket, browserPeerPath),
loginMethod: "Browser.LoginHandler",
})
@ -114,12 +115,11 @@ func updateCredsOnPeers(creds credential) map[string]error {
// response and not the reply.
err := client.Call("Browser.SetAuthPeer", &args, &GenericReply{})
// we try a bit hard (3 attempts with 1 second
// delay) to set creds on peers in case of
// failure.
// We try a bit hard (3 attempts with 1 second delay)
// to set creds on peers in case of failure.
if err != nil {
for i := 0; i < 2; i++ {
time.Sleep(1 * time.Second)
time.Sleep(1 * time.Second) // 1 second delay.
err = client.Call("Browser.SetAuthPeer", &args, &GenericReply{})
if err == nil {
break

View File

@ -0,0 +1,123 @@
/*
* Minio Cloud Storage, (C) 2016 Minio, Inc.
*
* 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 cmd
import (
"path"
"testing"
)
// API suite container common to both FS and XL.
type TestRPCBrowserPeerSuite struct {
serverType string
testServer TestServer
testAuthConf *authConfig
}
// Setting up the test suite and starting the Test server.
func (s *TestRPCBrowserPeerSuite) SetUpSuite(c *testing.T) {
s.testServer = StartTestBrowserPeerRPCServer(c, s.serverType)
s.testAuthConf = &authConfig{
address: s.testServer.Server.Listener.Addr().String(),
accessKey: s.testServer.AccessKey,
secretKey: s.testServer.SecretKey,
path: path.Join(reservedBucket, browserPeerPath),
loginMethod: "BrowserPeer.LoginHandler",
}
}
// No longer used with gocheck, but used in explicit teardown code in
// each test function. // Called implicitly by "gopkg.in/check.v1"
// after all tests are run.
func (s *TestRPCBrowserPeerSuite) TearDownSuite(c *testing.T) {
s.testServer.Stop()
}
func TestBrowserPeerRPC(t *testing.T) {
// setup code
s := &TestRPCBrowserPeerSuite{serverType: "XL"}
s.SetUpSuite(t)
// run test
s.testBrowserPeerRPC(t)
// teardown code
s.TearDownSuite(t)
}
// Tests for browser peer rpc.
func (s *TestRPCBrowserPeerSuite) testBrowserPeerRPC(t *testing.T) {
// Construct RPC call arguments.
creds := credential{
AccessKeyID: "abcd1",
SecretAccessKey: "abcd1234",
}
// Validate for invalid token.
args := SetAuthPeerArgs{Creds: creds}
args.Token = "garbage"
rclient := newClient(s.testAuthConf.address, s.testAuthConf.path, false)
defer rclient.Close()
err := rclient.Call("BrowserPeer.SetAuthPeer", &args, &GenericReply{})
if err != nil {
if err.Error() != errInvalidToken.Error() {
t.Fatal(err)
}
}
// Validate for successful Peer update.
args = SetAuthPeerArgs{Creds: creds}
client := newAuthClient(s.testAuthConf)
defer client.Close()
err = client.Call("BrowserPeer.SetAuthPeer", &args, &GenericReply{})
if err != nil {
t.Fatal(err)
}
// Validate for failure in login handler with previous credentials.
rclient = newClient(s.testAuthConf.address, s.testAuthConf.path, false)
defer rclient.Close()
rargs := &RPCLoginArgs{
Username: s.testAuthConf.accessKey,
Password: s.testAuthConf.secretKey,
}
rreply := &RPCLoginReply{}
err = rclient.Call("BrowserPeer.LoginHandler", rargs, rreply)
if err != nil {
if err.Error() != errInvalidAccessKeyID.Error() {
t.Fatal(err)
}
}
// Validate for success in loing handled with valid credetnails.
rargs = &RPCLoginArgs{
Username: creds.AccessKeyID,
Password: creds.SecretAccessKey,
}
rreply = &RPCLoginReply{}
err = rclient.Call("BrowserPeer.LoginHandler", rargs, rreply)
if err != nil {
t.Fatal(err)
}
// Validate all the replied fields after successful login.
if rreply.Token == "" {
t.Fatalf("Generated token cannot be empty %s", errInvalidToken)
}
if rreply.Timestamp.IsZero() {
t.Fatal("Time stamp returned cannot be zero")
}
}

View File

@ -27,24 +27,23 @@ import (
// throughout Minio cluster, initiated from a Minio browser session.
const (
browserPath = "/browser/setauth"
browserPeerPath = "/browser/setauth"
)
// The Type exporting methods exposed for RPC calls.
type browserAPIHandlers struct {
}
type browserPeerAPIHandlers struct{}
// Register RPC router
func registerBrowserRPCRouter(mux *router.Router) error {
browserHandlers := &browserAPIHandlers{}
func registerBrowserPeerRPCRouter(mux *router.Router) error {
bpHandlers := &browserPeerAPIHandlers{}
browserRPCServer := rpc.NewServer()
err := browserRPCServer.RegisterName("Browser", browserHandlers)
bpRPCServer := rpc.NewServer()
err := bpRPCServer.RegisterName("BrowserPeer", bpHandlers)
if err != nil {
return traceError(err)
}
browserRouter := mux.NewRoute().PathPrefix(reservedBucket).Subrouter()
browserRouter.Path(browserPath).Handler(browserRPCServer)
bpRouter := mux.NewRoute().PathPrefix(reservedBucket).Subrouter()
bpRouter.Path(browserPeerPath).Handler(bpRPCServer)
return nil
}

View File

@ -113,7 +113,7 @@ func configureServerHandler(srvCmdConfig serverCmdConfig) (http.Handler, error)
// By default minio web browser is enabled.
if !strings.EqualFold(os.Getenv("MINIO_BROWSER"), "off") {
// Register RPC router for web related calls.
if err = registerBrowserRPCRouter(mux); err != nil {
if err = registerBrowserPeerRPCRouter(mux); err != nil {
return nil, err
}

View File

@ -2056,3 +2056,33 @@ func initTestWebRPCEndPoint(objLayer ObjectLayer) http.Handler {
registerWebRouter(muxRouter)
return muxRouter
}
// Initialize browser RPC endpoint.
func initTestBrowserPeerRPCEndPoint() http.Handler {
// Initialize router.
muxRouter := router.NewRouter()
registerBrowserPeerRPCRouter(muxRouter)
return muxRouter
}
func StartTestBrowserPeerRPCServer(t TestErrHandler, instanceType string) TestServer {
root, err := newTestConfig("us-east-1")
if err != nil {
t.Fatalf("%s", err)
}
// Create an instance of TestServer.
testRPCServer := TestServer{}
// Fetch credentials for the test server.
credentials := serverConfig.GetCredential()
testRPCServer.Root = root
testRPCServer.AccessKey = credentials.AccessKeyID
testRPCServer.SecretKey = credentials.SecretAccessKey
// Initialize and run the TestServer.
testRPCServer.Server = httptest.NewServer(initTestBrowserPeerRPCEndPoint())
return testRPCServer
}

View File

@ -383,8 +383,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se
reply.PeerErrMsgs[svr] = errVal.Error()
}
// If we were unable to update locally, we return an error to
// the user/browser.
// If we were unable to update locally, we return an error to the user/browser.
if errsMap[globalMinioAddr] != nil {
// Since the error message may be very long to display
// on the browser, we tell the user to check the

View File

@ -590,7 +590,6 @@ func testSetAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandle
// Iterating over the test cases, calling the function under test and asserting the response.
for i, testCase := range testCases {
setAuthRequest := SetAuthArgs{AccessKey: testCase.username, SecretKey: testCase.password}
setAuthReply := &SetAuthReply{}
req, err := newTestWebRPCRequest("Web.SetAuth", authorization, setAuthRequest)