2015-03-20 16:37:08 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2014 The Kubernetes Authors All rights reserved .
2015-03-20 16:37:08 +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 .
* /
2015-09-11 19:22:01 +00:00
package status
2015-03-20 16:37:08 +00:00
import (
2015-06-22 19:31:46 +00:00
"fmt"
2015-03-20 16:37:08 +00:00
"math/rand"
"strconv"
"testing"
2015-05-09 05:01:43 +00:00
"time"
2015-03-20 16:37:08 +00:00
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
2015-09-17 22:21:55 +00:00
"k8s.io/kubernetes/pkg/api/unversioned"
2015-08-13 19:01:50 +00:00
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
2015-03-20 16:37:08 +00:00
)
2015-03-24 23:52:38 +00:00
var testPod * api . Pod = & api . Pod {
ObjectMeta : api . ObjectMeta {
UID : "12345678" ,
Name : "foo" ,
Namespace : "new" ,
} ,
}
2015-03-20 16:37:08 +00:00
2015-09-11 19:22:01 +00:00
func newTestManager ( ) * manager {
return NewManager ( & testclient . Fake { } ) . ( * manager )
2015-03-20 16:37:08 +00:00
}
func generateRandomMessage ( ) string {
return strconv . Itoa ( rand . Int ( ) )
}
func getRandomPodStatus ( ) api . PodStatus {
return api . PodStatus {
Message : generateRandomMessage ( ) ,
}
}
2015-08-03 13:21:11 +00:00
func verifyActions ( t * testing . T , kubeClient client . Interface , expectedActions [ ] testclient . Action ) {
2015-07-06 21:37:46 +00:00
actions := kubeClient . ( * testclient . Fake ) . Actions ( )
2015-03-20 16:37:08 +00:00
if len ( actions ) != len ( expectedActions ) {
t . Errorf ( "unexpected actions, got: %s expected: %s" , actions , expectedActions )
return
}
for i := 0 ; i < len ( actions ) ; i ++ {
2015-08-03 13:21:11 +00:00
e := expectedActions [ i ]
a := actions [ i ]
if ! a . Matches ( e . GetVerb ( ) , e . GetResource ( ) ) || a . GetSubresource ( ) != e . GetSubresource ( ) {
2015-03-20 16:37:08 +00:00
t . Errorf ( "unexpected actions, got: %s expected: %s" , actions , expectedActions )
}
}
}
2015-09-11 19:22:01 +00:00
func verifyUpdates ( t * testing . T , manager * manager , expectedUpdates int ) {
2015-03-25 16:32:16 +00:00
// Consume all updates in the channel.
numUpdates := 0
for {
hasUpdate := true
select {
case <- manager . podStatusChannel :
numUpdates ++
default :
hasUpdate = false
}
if ! hasUpdate {
break
}
}
if numUpdates != expectedUpdates {
2015-03-31 22:32:02 +00:00
t . Errorf ( "unexpected number of updates %d, expected %d" , numUpdates , expectedUpdates )
2015-03-25 16:32:16 +00:00
}
}
2015-03-20 16:37:08 +00:00
func TestNewStatus ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-03-24 23:52:38 +00:00
syncer . SetPodStatus ( testPod , getRandomPodStatus ( ) )
2015-03-25 16:32:16 +00:00
verifyUpdates ( t , syncer , 1 )
2015-05-09 05:01:43 +00:00
2015-08-18 20:26:56 +00:00
status , _ := syncer . GetPodStatus ( testPod . UID )
2015-05-09 05:01:43 +00:00
if status . StartTime . IsZero ( ) {
t . Errorf ( "SetPodStatus did not set a proper start time value" )
}
}
func TestNewStatusPreservesPodStartTime ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-05-09 05:01:43 +00:00
pod := & api . Pod {
ObjectMeta : api . ObjectMeta {
UID : "12345678" ,
Name : "foo" ,
Namespace : "new" ,
} ,
Status : api . PodStatus { } ,
}
2015-09-17 22:21:55 +00:00
now := unversioned . Now ( )
startTime := unversioned . NewTime ( now . Time . Add ( - 1 * time . Minute ) )
2015-05-09 05:01:43 +00:00
pod . Status . StartTime = & startTime
syncer . SetPodStatus ( pod , getRandomPodStatus ( ) )
2015-08-18 20:26:56 +00:00
status , _ := syncer . GetPodStatus ( pod . UID )
2015-05-09 05:01:43 +00:00
if ! status . StartTime . Time . Equal ( startTime . Time ) {
t . Errorf ( "Unexpected start time, expected %v, actual %v" , startTime , status . StartTime )
}
2015-03-20 16:37:08 +00:00
}
2015-09-29 20:04:08 +00:00
func getReadyPodStatus ( ) api . PodStatus {
return api . PodStatus {
Conditions : [ ] api . PodCondition {
{
Type : api . PodReady ,
Status : api . ConditionTrue ,
} ,
} ,
}
}
func TestNewStatusSetsReadyTransitionTime ( t * testing . T ) {
syncer := newTestManager ( )
podStatus := getReadyPodStatus ( )
pod := & api . Pod {
ObjectMeta : api . ObjectMeta {
UID : "12345678" ,
Name : "foo" ,
Namespace : "new" ,
} ,
Status : api . PodStatus { } ,
}
syncer . SetPodStatus ( pod , podStatus )
verifyUpdates ( t , syncer , 1 )
status , _ := syncer . GetPodStatus ( pod . UID )
readyCondition := api . GetPodReadyCondition ( status )
if readyCondition . LastTransitionTime . IsZero ( ) {
t . Errorf ( "Unexpected: last transition time not set" )
}
}
2015-03-20 16:37:08 +00:00
func TestChangedStatus ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-03-24 23:52:38 +00:00
syncer . SetPodStatus ( testPod , getRandomPodStatus ( ) )
syncer . SetPodStatus ( testPod , getRandomPodStatus ( ) )
2015-03-25 16:32:16 +00:00
verifyUpdates ( t , syncer , 2 )
2015-03-20 16:37:08 +00:00
}
2015-05-09 05:01:43 +00:00
func TestChangedStatusKeepsStartTime ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-09-17 22:21:55 +00:00
now := unversioned . Now ( )
2015-05-09 05:01:43 +00:00
firstStatus := getRandomPodStatus ( )
firstStatus . StartTime = & now
syncer . SetPodStatus ( testPod , firstStatus )
syncer . SetPodStatus ( testPod , getRandomPodStatus ( ) )
verifyUpdates ( t , syncer , 2 )
2015-08-18 20:26:56 +00:00
finalStatus , _ := syncer . GetPodStatus ( testPod . UID )
2015-05-09 05:01:43 +00:00
if finalStatus . StartTime . IsZero ( ) {
t . Errorf ( "StartTime should not be zero" )
}
if ! finalStatus . StartTime . Time . Equal ( now . Time ) {
t . Errorf ( "Expected %v, but got %v" , now . Time , finalStatus . StartTime . Time )
}
}
2015-09-29 20:04:08 +00:00
func TestChangedStatusUpdatesLastTransitionTime ( t * testing . T ) {
syncer := newTestManager ( )
podStatus := getReadyPodStatus ( )
pod := & api . Pod {
ObjectMeta : api . ObjectMeta {
UID : "12345678" ,
Name : "foo" ,
Namespace : "new" ,
} ,
Status : api . PodStatus { } ,
}
syncer . SetPodStatus ( pod , podStatus )
verifyUpdates ( t , syncer , 1 )
oldStatus , _ := syncer . GetPodStatus ( pod . UID )
anotherStatus := getReadyPodStatus ( )
anotherStatus . Conditions [ 0 ] . Status = api . ConditionFalse
syncer . SetPodStatus ( pod , anotherStatus )
verifyUpdates ( t , syncer , 1 )
newStatus , _ := syncer . GetPodStatus ( pod . UID )
oldReadyCondition := api . GetPodReadyCondition ( oldStatus )
newReadyCondition := api . GetPodReadyCondition ( newStatus )
if newReadyCondition . LastTransitionTime . IsZero ( ) {
t . Errorf ( "Unexpected: last transition time not set" )
}
if ! oldReadyCondition . LastTransitionTime . Before ( newReadyCondition . LastTransitionTime ) {
t . Errorf ( "Unexpected: new transition time %s, is not after old transition time %s" , newReadyCondition . LastTransitionTime , oldReadyCondition . LastTransitionTime )
}
}
2015-03-20 16:37:08 +00:00
func TestUnchangedStatus ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-03-20 16:37:08 +00:00
podStatus := getRandomPodStatus ( )
2015-03-24 23:52:38 +00:00
syncer . SetPodStatus ( testPod , podStatus )
syncer . SetPodStatus ( testPod , podStatus )
2015-03-25 16:32:16 +00:00
verifyUpdates ( t , syncer , 1 )
}
2015-09-29 20:04:08 +00:00
func TestUnchangedStatusPreservesLastTransitionTime ( t * testing . T ) {
syncer := newTestManager ( )
podStatus := getReadyPodStatus ( )
pod := & api . Pod {
ObjectMeta : api . ObjectMeta {
UID : "12345678" ,
Name : "foo" ,
Namespace : "new" ,
} ,
Status : api . PodStatus { } ,
}
syncer . SetPodStatus ( pod , podStatus )
verifyUpdates ( t , syncer , 1 )
oldStatus , _ := syncer . GetPodStatus ( pod . UID )
anotherStatus := getReadyPodStatus ( )
syncer . SetPodStatus ( pod , anotherStatus )
// No update.
verifyUpdates ( t , syncer , 0 )
newStatus , _ := syncer . GetPodStatus ( pod . UID )
oldReadyCondition := api . GetPodReadyCondition ( oldStatus )
newReadyCondition := api . GetPodReadyCondition ( newStatus )
if newReadyCondition . LastTransitionTime . IsZero ( ) {
t . Errorf ( "Unexpected: last transition time not set" )
}
if ! oldReadyCondition . LastTransitionTime . Equal ( newReadyCondition . LastTransitionTime ) {
t . Errorf ( "Unexpected: new transition time %s, is not equal to old transition time %s" , newReadyCondition . LastTransitionTime , oldReadyCondition . LastTransitionTime )
}
}
2015-07-28 20:06:05 +00:00
func TestSyncBatchIgnoresNotFound ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-07-28 20:06:05 +00:00
syncer . SetPodStatus ( testPod , getRandomPodStatus ( ) )
err := syncer . syncBatch ( )
if err != nil {
t . Errorf ( "unexpected syncing error: %v" , err )
}
verifyActions ( t , syncer . kubeClient , [ ] testclient . Action {
testclient . GetActionImpl { ActionImpl : testclient . ActionImpl { Verb : "get" , Resource : "pods" } } ,
} )
}
2015-03-25 16:32:16 +00:00
func TestSyncBatch ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-07-28 20:06:05 +00:00
syncer . kubeClient = testclient . NewSimpleFake ( testPod )
2015-03-25 16:32:16 +00:00
syncer . SetPodStatus ( testPod , getRandomPodStatus ( ) )
err := syncer . syncBatch ( )
if err != nil {
t . Errorf ( "unexpected syncing error: %v" , err )
}
2015-08-03 13:21:11 +00:00
verifyActions ( t , syncer . kubeClient , [ ] testclient . Action {
testclient . GetActionImpl { ActionImpl : testclient . ActionImpl { Verb : "get" , Resource : "pods" } } ,
testclient . UpdateActionImpl { ActionImpl : testclient . ActionImpl { Verb : "update" , Resource : "pods" , Subresource : "status" } } ,
} ,
)
2015-03-20 16:37:08 +00:00
}
2015-06-22 19:31:46 +00:00
2015-07-28 20:06:05 +00:00
func TestSyncBatchChecksMismatchedUID ( t * testing . T ) {
2015-09-11 19:22:01 +00:00
syncer := newTestManager ( )
2015-07-28 20:06:05 +00:00
testPod . UID = "first"
differentPod := * testPod
differentPod . UID = "second"
syncer . kubeClient = testclient . NewSimpleFake ( testPod )
syncer . SetPodStatus ( & differentPod , getRandomPodStatus ( ) )
err := syncer . syncBatch ( )
if err != nil {
t . Errorf ( "unexpected syncing error: %v" , err )
}
verifyActions ( t , syncer . kubeClient , [ ] testclient . Action {
testclient . GetActionImpl { ActionImpl : testclient . ActionImpl { Verb : "get" , Resource : "pods" } } ,
} )
}
2015-06-22 19:31:46 +00:00
// shuffle returns a new shuffled list of container statuses.
func shuffle ( statuses [ ] api . ContainerStatus ) [ ] api . ContainerStatus {
numStatuses := len ( statuses )
randIndexes := rand . Perm ( numStatuses )
shuffled := make ( [ ] api . ContainerStatus , numStatuses )
for i := 0 ; i < numStatuses ; i ++ {
shuffled [ i ] = statuses [ randIndexes [ i ] ]
}
return shuffled
}
func TestStatusEquality ( t * testing . T ) {
containerStatus := [ ] api . ContainerStatus { }
for i := 0 ; i < 10 ; i ++ {
s := api . ContainerStatus {
Name : fmt . Sprintf ( "container%d" , i ) ,
}
containerStatus = append ( containerStatus , s )
}
podStatus := api . PodStatus {
ContainerStatuses : containerStatus ,
}
for i := 0 ; i < 10 ; i ++ {
oldPodStatus := api . PodStatus {
ContainerStatuses : shuffle ( podStatus . ContainerStatuses ) ,
}
if ! isStatusEqual ( & oldPodStatus , & podStatus ) {
t . Fatalf ( "Order of container statuses should not affect equality." )
}
}
}