Files
my-rook-config/pkg/rook/client/client_test.go
T
Travis Nielsen ba628c6307 cephfs: create file system with a CRD
- multiple file systems are allowed
- multiple mds instances are allowed per file system.
- a keyring is created per mds instance
- double the desired mds instances are started, half in standby mode
2017-10-05 14:21:48 -07:00

414 lines
14 KiB
Go

/*
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 client
import (
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/rook/rook/pkg/model"
"github.com/stretchr/testify/assert"
)
const (
SuccessGetNodesContent = `[{"nodeID": "node1","publicIp": "1.2.3.100","privateIp": "10.0.0.100","storage": 100},{"nodeID": "node2","ipAddr": "10.0.0.101","storage": 200}]`
SuccessGetPoolsContent = "[{\"poolName\":\"rbd\",\"poolNum\":0,\"type\":0,\"replicatedConfig\":{\"size\":1},\"erasureCodedConfig\":{\"dataChunkCount\":0,\"codingChunkCount\":0,\"algorithm\":\"\"}},{\"poolName\":\"ecPool1\",\"poolNum\":1,\"type\":1,\"replicatedConfig\":{\"size\":0},\"erasureCodedConfig\":{\"dataChunkCount\":2,\"codingChunkCount\":1,\"algorithm\":\"jerasure::reed_sol_van\"}}]"
SuccessCreatePoolContent = `pool 'ecPool1' created`
SuccessGetBlockImagesContent = `[{"imageName":"myimage1","poolName":"rbd","size":10485760,"device":"","mountPoint":""},{"imageName":"myimage2","poolName":"rbd2","size":10485761,"device":"","mountPoint":""}]`
SuccessCreateBlockImageContent = `succeeded created image myimage3`
SuccessDeleteBlockImageContent = `succeeded deleting image myimage3`
SuccessGetClientAccessInfoContent = `{"monAddresses":["10.37.129.214:6790/0"],"userName":"admin","secretKey":"AQBsCv1X5oD9GhAARHVU9N+kFRWDjyLA1dqzIg=="}`
SuccessGetFilesystemsContent = `[{"name":"myfs1","metadataPool":"myfs1-metadata","dataPools":["myfs1-data"]}]`
SuccessGetObjectStoreConnectionInfoContent = `{"host":"rook-ceph-rgw-default:12345", "accessKey":"UST0JAP8CE61FDE0Q4BE", "secretKey":"tVCuH20xTokjEpVJc7mKjL8PLTfGh4NZ3le3zg9X"}`
)
func TestURL(t *testing.T) {
client := NewRookNetworkRestClient(GetRestURL("10.0.1.2:8124"), http.DefaultClient)
assert.Equal(t, "http://10.0.1.2:8124", client.URL())
}
func TestRookRestError(t *testing.T) {
err := RookRestError{Query: "foo", Status: http.StatusBadRequest, Body: []byte("error body")}
assert.Equal(t, "HTTP status code 400 for query foo: 'error body'", err.Error())
}
func TestGetNodes(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessGetNodesContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
// invoke the GetNodes method that will use our mock http client/server to return a successful response
getNodesResponse, err := client.GetNodes()
assert.Nil(t, err)
assert.NotNil(t, getNodesResponse)
assert.Equal(t, 2, len(getNodesResponse))
var testNode model.Node
for i := range getNodesResponse {
if getNodesResponse[i].NodeID == "node1" {
testNode = getNodesResponse[i]
break
}
}
assert.NotNil(t, testNode)
assert.Equal(t, "1.2.3.100", testNode.PublicIP)
assert.Equal(t, "10.0.0.100", testNode.PrivateIP)
assert.Equal(t, uint64(100), testNode.Storage)
}
func TestGetPools(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessGetPoolsContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
// invoke the GetPools method that will use our mock http client/server to return a successful response
getPoolsResponse, err := client.GetPools()
assert.Nil(t, err)
assert.NotNil(t, getPoolsResponse)
assert.Equal(t, 2, len(getPoolsResponse))
expectedPool1 := model.Pool{
Name: "ecPool1",
Number: 1,
Type: model.ErasureCoded,
ErasureCodedConfig: model.ErasureCodedPoolConfig{
DataChunkCount: 2,
CodingChunkCount: 1,
Algorithm: "jerasure::reed_sol_van",
},
}
var actualPool model.Pool
for i := range getPoolsResponse {
if getPoolsResponse[i].Name == "ecPool1" {
actualPool = getPoolsResponse[i]
break
}
}
assert.NotNil(t, actualPool)
assert.Equal(t, expectedPool1, actualPool)
}
func TestCreatePool(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessCreatePoolContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
// invoke the CreatePool method that will use our mock http client/server to return a successful response
newPool := model.Pool{
Name: "ecPool1",
Number: 1,
Type: model.ErasureCoded,
ErasureCodedConfig: model.ErasureCodedPoolConfig{
DataChunkCount: 2,
CodingChunkCount: 1,
Algorithm: "jerasure::reed_sol_van",
},
}
createPoolResponse, err := client.CreatePool(newPool)
assert.Nil(t, err)
assert.Equal(t, "pool 'ecPool1' created\n", createPoolResponse)
}
func TestGetBlockImages(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessGetBlockImagesContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
getBlockImagesResponse, err := client.GetBlockImages()
assert.Nil(t, err)
assert.Equal(t, 2, len(getBlockImagesResponse))
expectedImage := model.BlockImage{
Name: "myimage2",
PoolName: "rbd2",
Size: 10485761,
}
var actualImage *model.BlockImage
for i := range getBlockImagesResponse {
if getBlockImagesResponse[i].Name == expectedImage.Name {
actualImage = &(getBlockImagesResponse[i])
break
}
}
assert.NotNil(t, actualImage)
assert.Equal(t, expectedImage, *actualImage)
}
func TestCreateBlockImage(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessCreateBlockImageContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
newImage := model.BlockImage{
Name: "myimage3",
PoolName: "rbd2",
Size: 10485762,
}
response, err := client.CreateBlockImage(newImage)
assert.Nil(t, err)
assert.Equal(t, SuccessCreateBlockImageContent+"\n", response)
}
func TestDeleteBlockImage(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessDeleteBlockImageContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
deleteImage := model.BlockImage{
Name: "myimage3",
PoolName: "rbd2",
}
response, err := client.DeleteBlockImage(deleteImage)
assert.Nil(t, err)
assert.Equal(t, SuccessDeleteBlockImageContent+"\n", response)
}
func TestGetClientAccessInfo(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessGetClientAccessInfoContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
expectedClientAccessInfo := model.ClientAccessInfo{
MonAddresses: []string{"10.37.129.214:6790/0"},
UserName: "admin",
SecretKey: "AQBsCv1X5oD9GhAARHVU9N+kFRWDjyLA1dqzIg==",
}
actualClientAccessInfo, err := client.GetClientAccessInfo()
assert.Nil(t, err)
assert.Equal(t, expectedClientAccessInfo, actualClientAccessInfo)
}
func TestGetFilesystems(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessGetFilesystemsContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
expectedFilesystems := []model.Filesystem{
{Name: "myfs1", MetadataPool: "myfs1-metadata", DataPools: []string{"myfs1-data"}},
}
actualFilesystems, err := client.GetFilesystems()
assert.Nil(t, err)
assert.Equal(t, expectedFilesystems, actualFilesystems)
}
func TestCreateFilesystem(t *testing.T) {
mockServer := NewMockHttpServer(202, "")
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
fsr := model.FilesystemRequest{Name: "myfs1"}
resp, err := client.CreateFilesystem(fsr)
assert.NotNil(t, err)
assert.True(t, IsHttpAccepted(err))
assert.Equal(t, "", resp)
}
func TestDeleteFilesystem(t *testing.T) {
mockServer := NewMockHttpServer(202, "")
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
fsr := model.FilesystemRequest{Name: "myfs1"}
resp, err := client.DeleteFilesystem(fsr)
assert.NotNil(t, err)
assert.True(t, IsHttpAccepted(err))
assert.Equal(t, "", resp)
}
func TestCreateObjectStore(t *testing.T) {
mockServer := NewMockHttpServer(202, "")
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
store := model.ObjectStore{Name: "default", Gateway: model.Gateway{Port: 123}}
resp, err := client.CreateObjectStore(store)
assert.NotNil(t, err)
assert.True(t, IsHttpAccepted(err))
assert.Equal(t, "", resp)
}
func TestGetObjectStoreConnectionInfo(t *testing.T) {
mockServer := NewMockHttpServer(200, SuccessGetObjectStoreConnectionInfoContent)
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
expectedResp := model.ObjectStoreConnectInfo{
Host: "rook-ceph-rgw-default:12345",
}
resp, err := client.GetObjectStoreConnectionInfo("default")
assert.Nil(t, err)
assert.Equal(t, expectedResp, *resp)
}
func TestGetNodesFailure(t *testing.T) {
ClientFailureHelper(t, func(client RookRestClient) (interface{}, error) { return client.GetNodes() })
}
func TestGetPoolsFailure(t *testing.T) {
ClientFailureHelper(t, func(client RookRestClient) (interface{}, error) { return client.GetPools() })
}
func TestCreatePoolFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.CreatePool(model.Pool{Name: "pool1"})
}
verifyFunc := getStringVerifyFunc(t)
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestGetBlockImagesFailure(t *testing.T) {
ClientFailureHelper(t, func(client RookRestClient) (interface{}, error) { return client.GetBlockImages() })
}
func TestCreateBlockImageFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.CreateBlockImage(model.BlockImage{Name: "image1"})
}
verifyFunc := getStringVerifyFunc(t)
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestDeleteBlockImageFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.DeleteBlockImage(model.BlockImage{Name: "image1"})
}
verifyFunc := getStringVerifyFunc(t)
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestGetClientAccessInfoFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.GetClientAccessInfo()
}
verifyFunc := func(resp interface{}, err error) {
assert.NotNil(t, err)
assert.Equal(t, model.ClientAccessInfo{}, resp.(model.ClientAccessInfo))
}
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestGetFilesystemsFailure(t *testing.T) {
ClientFailureHelper(t, func(client RookRestClient) (interface{}, error) { return client.GetFilesystems() })
}
func TestCreateFilesystemFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.CreateFilesystem(model.FilesystemRequest{Name: "myfs1"})
}
verifyFunc := getStringVerifyFunc(t)
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestDeleteFilesystemFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.DeleteFilesystem(model.FilesystemRequest{Name: "myfs1"})
}
verifyFunc := getStringVerifyFunc(t)
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestCreateObjectStoreFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.CreateObjectStore(model.ObjectStore{Name: "name"})
}
verifyFunc := getStringVerifyFunc(t)
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func TestGetObjectStoreConnectionInfoFailure(t *testing.T) {
clientFunc := func(client RookRestClient) (interface{}, error) {
return client.GetObjectStoreConnectionInfo("default")
}
verifyFunc := func(resp interface{}, err error) {
assert.NotNil(t, err)
assert.Nil(t, resp)
}
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func ClientFailureHelper(t *testing.T, clientFunc func(RookRestClient) (interface{}, error)) {
verifyFunc := func(resp interface{}, err error) {
assert.NotNil(t, err)
assert.Nil(t, resp)
}
ClientFailureHelperWithVerification(t, clientFunc, verifyFunc)
}
func ClientFailureHelperWithVerification(t *testing.T, clientFunc func(RookRestClient) (interface{}, error),
verifyFunc func(interface{}, error)) {
mockServer := NewMockHttpServer(500, "something went wrong!")
defer mockServer.Close()
mockHttpClient := NewMockHttpClient(mockServer.URL)
client := NewRookNetworkRestClient(mockServer.URL, mockHttpClient)
// invoke the client func
resp, err := clientFunc(client)
// invoke the verification func to verify resp and err
verifyFunc(resp, err)
}
func getStringVerifyFunc(t *testing.T) func(resp interface{}, err error) {
return func(resp interface{}, err error) {
assert.NotNil(t, err)
assert.Equal(t, "", resp.(string))
}
}
func NewMockHttpServer(responseStatusCode int, responseBody string) *httptest.Server {
// create and return a mock http server that will return the specified HTTP status code and response body content
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(responseStatusCode)
w.Header().Set("Content-Type", "application/json")
fmt.Fprintln(w, responseBody)
}))
}
func NewMockHttpClient(mockServerURL string) *http.Client {
// create a transport that will use direct all network traffic to the mock HTTP server
transport := &http.Transport{
Proxy: func(request *http.Request) (*url.URL, error) {
return url.Parse(mockServerURL)
},
}
// return a http client that uses our transport
return &http.Client{Transport: transport}
}