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

master
Harshavardhana 8 years ago committed by GitHub
parent 286a8924fd
commit 33c771bb3e
  1. 20
      cmd/browser-peer-rpc.go
  2. 123
      cmd/browser-peer-rpc_test.go
  3. 17
      cmd/browser-rpc-router.go
  4. 2
      cmd/routers.go
  5. 30
      cmd/test-utils_test.go
  6. 3
      cmd/web-handlers.go
  7. 1
      cmd/web-handlers_test.go

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

@ -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")
}
}

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

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

@ -2056,3 +2056,33 @@ func initTestWebRPCEndPoint(objLayer ObjectLayer) http.Handler {
registerWebRouter(muxRouter) registerWebRouter(muxRouter)
return 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
}

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

@ -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. // Iterating over the test cases, calling the function under test and asserting the response.
for i, testCase := range testCases { for i, testCase := range testCases {
setAuthRequest := SetAuthArgs{AccessKey: testCase.username, SecretKey: testCase.password} setAuthRequest := SetAuthArgs{AccessKey: testCase.username, SecretKey: testCase.password}
setAuthReply := &SetAuthReply{} setAuthReply := &SetAuthReply{}
req, err := newTestWebRPCRequest("Web.SetAuth", authorization, setAuthRequest) req, err := newTestWebRPCRequest("Web.SetAuth", authorization, setAuthRequest)

Loading…
Cancel
Save