mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
226 lines
6.6 KiB
Go
226 lines
6.6 KiB
Go
//
|
|
// DISCLAIMER
|
|
//
|
|
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
|
|
//
|
|
// 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.
|
|
//
|
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
//
|
|
// Author Ewout Prangsma
|
|
//
|
|
|
|
package tests
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/dchest/uniuri"
|
|
|
|
driver "github.com/arangodb/go-driver"
|
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
|
|
"github.com/arangodb/kube-arangodb/pkg/client"
|
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
|
)
|
|
|
|
func TestLoadBalancingCursorVST(t *testing.T) {
|
|
longOrSkip(t)
|
|
// run with VST
|
|
loadBalancingCursorSubtest(t, true)
|
|
}
|
|
|
|
func TestLoadBalancingCursorHTTP(t *testing.T) {
|
|
longOrSkip(t)
|
|
// run with HTTP
|
|
loadBalancingCursorSubtest(t, false)
|
|
}
|
|
|
|
func wasForwarded(r driver.Response) bool {
|
|
h := r.Header("x-arango-request-forwarded-to")
|
|
return h != ""
|
|
}
|
|
|
|
// tests cursor forwarding with load-balanced conn.
|
|
func loadBalancingCursorSubtest(t *testing.T, useVst bool) {
|
|
c := client.MustNewInCluster()
|
|
kubecli := mustNewKubeClient(t)
|
|
ns := getNamespace(t)
|
|
|
|
// Prepare deployment config
|
|
namePrefix := "test-lb-"
|
|
if useVst {
|
|
namePrefix += "vst-"
|
|
} else {
|
|
namePrefix += "http-"
|
|
}
|
|
depl := newDeployment(namePrefix + uniuri.NewLen(4))
|
|
depl.Spec.Mode = api.NewMode(api.DeploymentModeCluster)
|
|
depl.Spec.Image = util.NewString("arangodb/arangodb:3.3.13") // Note: 3.3.13 is the first version supporting the cursor forwarding feature.
|
|
|
|
// Create deployment
|
|
_, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl)
|
|
if err != nil {
|
|
t.Fatalf("Create deployment failed: %v", err)
|
|
}
|
|
// Prepare cleanup
|
|
defer removeDeployment(c, depl.GetName(), ns)
|
|
|
|
// Wait for deployment to be ready
|
|
apiObject, err := waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady())
|
|
if err != nil {
|
|
t.Fatalf("Deployment not running in time: %v", err)
|
|
}
|
|
|
|
// Create a database client
|
|
ctx := context.Background()
|
|
clOpts := &DatabaseClientOptions{
|
|
UseVST: useVst,
|
|
ShortTimeout: true,
|
|
}
|
|
client := mustNewArangodDatabaseClient(ctx, kubecli, apiObject, t, clOpts)
|
|
|
|
// Wait for cluster to be available
|
|
if err := waitUntilVersionUp(client, nil); err != nil {
|
|
t.Fatalf("Cluster not running returning version in time: %v", err)
|
|
}
|
|
|
|
// Create data set
|
|
collectionData := map[string][]interface{}{
|
|
"books": []interface{}{
|
|
Book{Title: "Book 01"},
|
|
Book{Title: "Book 02"},
|
|
Book{Title: "Book 03"},
|
|
Book{Title: "Book 04"},
|
|
Book{Title: "Book 05"},
|
|
Book{Title: "Book 06"},
|
|
Book{Title: "Book 07"},
|
|
Book{Title: "Book 08"},
|
|
Book{Title: "Book 09"},
|
|
Book{Title: "Book 10"},
|
|
Book{Title: "Book 11"},
|
|
Book{Title: "Book 12"},
|
|
Book{Title: "Book 13"},
|
|
Book{Title: "Book 14"},
|
|
Book{Title: "Book 15"},
|
|
Book{Title: "Book 16"},
|
|
Book{Title: "Book 17"},
|
|
Book{Title: "Book 18"},
|
|
Book{Title: "Book 19"},
|
|
Book{Title: "Book 20"},
|
|
},
|
|
"users": []interface{}{
|
|
UserDoc{Name: "John", Age: 13},
|
|
UserDoc{Name: "Jake", Age: 25},
|
|
UserDoc{Name: "Clair", Age: 12},
|
|
UserDoc{Name: "Johnny", Age: 42},
|
|
UserDoc{Name: "Blair", Age: 67},
|
|
UserDoc{Name: "Zz", Age: 12},
|
|
},
|
|
}
|
|
|
|
db := ensureDatabase(ctx, client, "lb_cursor_test", nil, t)
|
|
for colName, colDocs := range collectionData {
|
|
col := ensureCollection(ctx, db, colName, nil, t)
|
|
if _, _, err := col.CreateDocuments(ctx, colDocs); err != nil {
|
|
t.Fatalf("Expected success, got %s", err)
|
|
}
|
|
}
|
|
|
|
// Setup tests
|
|
tests := []queryTest{
|
|
queryTest{
|
|
Query: "FOR d IN books SORT d.Title RETURN d",
|
|
ExpectSuccess: true,
|
|
ExpectedDocuments: collectionData["books"],
|
|
DocumentType: reflect.TypeOf(Book{}),
|
|
},
|
|
}
|
|
|
|
var r driver.Response
|
|
// Setup context
|
|
ctx = driver.WithResponse(driver.WithQueryBatchSize(nil, 1), &r)
|
|
|
|
// keep track of whether at least one request was forwarded internally to the
|
|
// correct coordinator behind the load balancer
|
|
someRequestsForwarded := false
|
|
someRequestsNotForwarded := false
|
|
|
|
// Run tests for every context alternative
|
|
for i, test := range tests {
|
|
cursor, err := db.Query(ctx, test.Query, test.BindVars)
|
|
if err == nil {
|
|
// Close upon exit of the function
|
|
defer cursor.Close()
|
|
}
|
|
if test.ExpectSuccess {
|
|
if err != nil {
|
|
t.Errorf("Expected success in query %d (%s), got '%s'", i, test.Query, err)
|
|
continue
|
|
}
|
|
if count := cursor.Count(); count != 0 {
|
|
t.Errorf("Expected count of 0, got %d in query %d (%s)", count, i, test.Query)
|
|
}
|
|
var result []interface{}
|
|
for {
|
|
hasMore := cursor.HasMore()
|
|
doc := reflect.New(test.DocumentType)
|
|
if _, err := cursor.ReadDocument(ctx, doc.Interface()); driver.IsNoMoreDocuments(err) {
|
|
if hasMore {
|
|
t.Error("HasMore returned true, but ReadDocument returns a IsNoMoreDocuments error")
|
|
}
|
|
break
|
|
} else if err != nil {
|
|
t.Errorf("Failed to result document %d: %s", len(result), err)
|
|
}
|
|
if !hasMore {
|
|
t.Error("HasMore returned false, but ReadDocument returns a document")
|
|
}
|
|
result = append(result, doc.Elem().Interface())
|
|
if wasForwarded(r) {
|
|
someRequestsForwarded = true
|
|
} else {
|
|
someRequestsNotForwarded = true
|
|
}
|
|
time.Sleep(200 * time.Millisecond)
|
|
}
|
|
if len(result) != len(test.ExpectedDocuments) {
|
|
t.Errorf("Expected %d documents, got %d in query %d (%s)", len(test.ExpectedDocuments), len(result), i, test.Query)
|
|
} else {
|
|
for resultIdx, resultDoc := range result {
|
|
if !reflect.DeepEqual(resultDoc, test.ExpectedDocuments[resultIdx]) {
|
|
t.Errorf("Unexpected document in query %d (%s) at index %d: got %+v, expected %+v", i, test.Query, resultIdx, resultDoc, test.ExpectedDocuments[resultIdx])
|
|
}
|
|
}
|
|
}
|
|
// Close anyway (this tests calling Close more than once)
|
|
if err := cursor.Close(); err != nil {
|
|
t.Errorf("Expected success in Close of cursor from query %d (%s), got '%s'", i, test.Query, err)
|
|
}
|
|
} else {
|
|
if err == nil {
|
|
t.Errorf("Expected error in query %d (%s), got '%s'", i, test.Query, err)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
if !someRequestsForwarded {
|
|
t.Error("Did not detect any request being forwarded behind load balancer!")
|
|
}
|
|
if !someRequestsNotForwarded {
|
|
t.Error("Did not detect any request NOT being forwarded behind load balancer!")
|
|
}
|
|
}
|