2015-08-25 17:48:41 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2015 The Kubernetes Authors .
2015-08-25 17:48:41 +00:00
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 e2e
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"syscall"
"time"
2015-12-10 14:35:58 +00:00
2016-12-14 01:18:17 +00:00
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
2016-04-07 17:21:31 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2015-12-10 14:35:58 +00:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
2015-08-25 17:48:41 +00:00
)
const (
2016-02-19 23:44:13 +00:00
k8bpsContainerVersion = "r.2.8.19" // Container version, see the examples/k8petstore dockerfiles for details.
2016-04-07 17:21:31 +00:00
k8bpsThroughputDummy = "0" // Polling time = 0, since we framework.Poll in ginkgo rather than using the shell script tests.
2016-02-19 23:44:13 +00:00
k8bpsRedisSlaves = "1" // Number of redis slaves.
k8bpsDontRunTest = "0" // Don't bother embedded test.
k8bpsStartupTimeout = 30 * time . Second // Amount of elapsed time before petstore transactions are being stored.
k8bpsMinTransactionsOnStartup = 3 // Amount of transactions we expect we should have before data generator starts.
2015-08-25 17:48:41 +00:00
// Constants for the first test. We can make this a hashmap once we add scale tests to it.
2016-02-19 23:44:13 +00:00
k8bpsSmokeTestFinalTransactions = 50
k8bpsSmokeTestTimeout = 60 * time . Second
2015-08-25 17:48:41 +00:00
)
// readTransactions reads # of transactions from the k8petstore web server endpoint.
// for more details see the source of the k8petstore web server.
2016-10-18 13:00:38 +00:00
func readTransactions ( c clientset . Interface , ns string ) ( error , int ) {
proxyRequest , errProxy := framework . GetServicesProxyRequest ( c , c . Core ( ) . RESTClient ( ) . Get ( ) )
2015-11-18 03:42:03 +00:00
if errProxy != nil {
return errProxy , - 1
}
body , err := proxyRequest . Namespace ( ns ) .
2015-08-25 17:48:41 +00:00
Name ( "frontend" ) .
Suffix ( "llen" ) .
DoRaw ( )
if err != nil {
return err , - 1
} else {
totalTrans , err := strconv . Atoi ( string ( body ) )
return err , totalTrans
}
}
// runK8petstore runs the k8petstore application, bound to external nodeport, and
2016-02-19 23:44:13 +00:00
// polls until finalTransactionsExpected transactions are acquired, in a maximum of maxSeconds.
2016-10-18 13:00:38 +00:00
func runK8petstore ( restServers int , loadGenerators int , c clientset . Interface , ns string , finalTransactionsExpected int , maxTime time . Duration ) {
2015-08-25 17:48:41 +00:00
var err error = nil
2016-04-07 17:21:31 +00:00
k8bpsScriptLocation := filepath . Join ( framework . TestContext . RepoRoot , "examples/k8petstore/k8petstore-nodeport.sh" )
2015-08-25 17:48:41 +00:00
cmd := exec . Command (
k8bpsScriptLocation ,
2016-04-07 17:21:31 +00:00
framework . TestContext . KubectlPath ,
2015-08-25 17:48:41 +00:00
k8bpsContainerVersion ,
k8bpsThroughputDummy ,
strconv . Itoa ( restServers ) ,
strconv . Itoa ( loadGenerators ) ,
k8bpsRedisSlaves ,
k8bpsDontRunTest , // Don't bother embedded test.
ns ,
)
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
2016-04-07 17:21:31 +00:00
framework . Logf ( "Starting k8petstore application...." )
2015-08-25 17:48:41 +00:00
// Run the k8petstore app, and log / fail if it returns any errors.
// This should return quickly, assuming containers are downloaded.
if err = cmd . Start ( ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "%v" , err )
2015-08-25 17:48:41 +00:00
}
// Make sure there are no command errors.
if err = cmd . Wait ( ) ; err != nil {
if exiterr , ok := err . ( * exec . ExitError ) ; ok {
if status , ok := exiterr . Sys ( ) . ( syscall . WaitStatus ) ; ok {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Exit Status: %d" , status . ExitStatus ( ) )
2015-08-25 17:48:41 +00:00
}
}
}
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-07 17:21:31 +00:00
framework . Logf ( "... Done starting k8petstore " )
2015-08-25 17:48:41 +00:00
totalTransactions := 0
2016-04-07 17:21:31 +00:00
framework . Logf ( "Start polling, timeout is %v seconds" , maxTime )
2015-08-25 17:48:41 +00:00
// How long until the FIRST transactions are created.
startupTimeout := time . After ( time . Duration ( k8bpsStartupTimeout ) )
// Maximum time to wait until we reach the nth transaction.
transactionsCompleteTimeout := time . After ( time . Duration ( maxTime ) )
tick := time . Tick ( 2 * time . Second )
var ready = false
2016-04-07 17:21:31 +00:00
framework . Logf ( "Now waiting %v seconds to see progress (transactions > 3)" , k8bpsStartupTimeout )
2015-08-25 17:48:41 +00:00
T :
for {
select {
case <- transactionsCompleteTimeout :
2016-04-07 17:21:31 +00:00
framework . Logf ( "Completion timeout %v reached, %v transactions not complete. Breaking!" , time . Duration ( maxTime ) , finalTransactionsExpected )
2015-08-25 17:48:41 +00:00
break T
case <- tick :
2016-02-19 23:44:13 +00:00
// Don't fail if there's an error. We expect a few failures might happen in the cloud.
2015-08-25 17:48:41 +00:00
err , totalTransactions = readTransactions ( c , ns )
2016-02-19 23:44:13 +00:00
if err == nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "PetStore : Time: %v, %v = total petstore transactions stored into redis." , time . Now ( ) , totalTransactions )
2016-02-19 23:44:13 +00:00
if totalTransactions >= k8bpsMinTransactionsOnStartup {
ready = true
}
if totalTransactions >= finalTransactionsExpected {
break T
}
} else {
if ready {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Blip: during polling: %v" , err )
2016-02-19 23:44:13 +00:00
} else {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Not ready yet: %v" , err )
2016-02-19 23:44:13 +00:00
}
2015-08-25 17:48:41 +00:00
}
2016-02-19 23:44:13 +00:00
case <- startupTimeout :
if ! ready {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Startup Timeout %v reached: Its been too long and we still haven't started accumulating %v transactions!" , startupTimeout , k8bpsMinTransactionsOnStartup )
2015-08-25 17:48:41 +00:00
break T
}
}
}
2016-02-19 23:44:13 +00:00
// We should have exceeded the finalTransactionsExpected num of transactions.
2015-08-25 17:48:41 +00:00
// If this fails, but there are transactions being created, we may need to recalibrate
2016-02-19 23:44:13 +00:00
// the finalTransactionsExpected value - or else - your cluster is broken/slow !
Ω ( totalTransactions ) . Should ( BeNumerically ( ">" , finalTransactionsExpected ) )
2015-08-25 17:48:41 +00:00
}
2016-04-07 17:21:31 +00:00
var _ = framework . KubeDescribe ( "Pet Store [Feature:Example]" , func ( ) {
2015-08-25 17:48:41 +00:00
2016-03-11 17:24:24 +00:00
BeforeEach ( func ( ) {
// The shell scripts in k8petstore break on jenkins... Pure golang rewrite is in progress.
2016-04-07 17:21:31 +00:00
framework . SkipUnlessProviderIs ( "local" )
2016-03-11 17:24:24 +00:00
} )
2015-12-10 14:35:58 +00:00
// The number of nodes dictates total number of generators/transaction expectations.
var nodeCount int
2016-04-07 17:21:31 +00:00
f := framework . NewDefaultFramework ( "petstore" )
2015-08-25 17:48:41 +00:00
2016-02-19 23:44:13 +00:00
It ( fmt . Sprintf ( "should scale to persist a nominal number ( %v ) of transactions in %v seconds" , k8bpsSmokeTestFinalTransactions , k8bpsSmokeTestTimeout ) , func ( ) {
2016-10-19 13:55:39 +00:00
nodes := framework . GetReadySchedulableNodesOrDie ( f . ClientSet )
2015-12-10 14:35:58 +00:00
nodeCount = len ( nodes . Items )
2015-08-25 17:48:41 +00:00
2015-12-10 14:35:58 +00:00
loadGenerators := nodeCount
restServers := nodeCount
2015-08-25 17:48:41 +00:00
fmt . Printf ( "load generators / rest servers [ %v / %v ] " , loadGenerators , restServers )
2016-10-18 13:00:38 +00:00
runK8petstore ( restServers , loadGenerators , f . ClientSet , f . Namespace . Name , k8bpsSmokeTestFinalTransactions , k8bpsSmokeTestTimeout )
2015-08-25 17:48:41 +00:00
} )
} )