2017-12-29 05:43:38 -05:00
/ *
Copyright 2017 The Kubernetes Authors .
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 .
* /
2019-11-06 22:59:05 -05:00
package e2enode
2017-12-29 05:43:38 -05:00
import (
2020-02-07 21:16:47 -05:00
"context"
2017-12-29 05:43:38 -05:00
"path/filepath"
"time"
2019-12-09 03:09:29 -05:00
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/test/e2e/framework/testfiles"
2017-12-29 05:43:38 -05:00
"regexp"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2018-01-24 12:06:07 -05:00
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/kubernetes/pkg/features"
2018-08-29 12:07:52 -04:00
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
2019-08-27 05:18:43 -04:00
kubeletpodresourcesv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/podresources/v1alpha1"
2017-12-29 05:43:38 -05:00
"k8s.io/kubernetes/test/e2e/framework"
2018-08-28 02:41:42 -04:00
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
2019-05-07 20:09:50 -04:00
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
2017-12-29 05:43:38 -05:00
2019-07-28 00:49:36 -04:00
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
2017-12-29 05:43:38 -05:00
)
2018-01-11 01:41:45 -05:00
const (
2019-12-09 03:09:29 -05:00
// sampleResourceName is the name of the example resource which is used in the e2e test
sampleResourceName = "example.com/resource"
// sampleDevicePluginDSYAML is the path of the daemonset template of the sample device plugin. // TODO: Parametrize it by making it a feature in TestFramework.
sampleDevicePluginDSYAML = "test/e2e/testing-manifests/sample-device-plugin.yaml"
// sampleDevicePluginName is the name of the device plugin pod
sampleDevicePluginName = "sample-device-plugin"
2018-01-11 01:41:45 -05:00
// fake resource name
2018-08-28 02:41:42 -04:00
resourceName = "example.com/resource"
envVarNamePluginSockDir = "PLUGIN_SOCK_DIR"
2018-01-11 01:41:45 -05:00
)
2019-12-09 03:09:29 -05:00
var (
appsScheme = runtime . NewScheme ( )
appsCodecs = serializer . NewCodecFactory ( appsScheme )
)
2018-01-11 01:41:45 -05:00
// Serial because the test restarts Kubelet
2018-01-24 12:06:07 -05:00
var _ = framework . KubeDescribe ( "Device Plugin [Feature:DevicePluginProbe][NodeFeature:DevicePluginProbe][Serial]" , func ( ) {
f := framework . NewDefaultFramework ( "device-plugin-errors" )
2019-03-12 15:58:23 -04:00
testDevicePlugin ( f , "/var/lib/kubelet/plugins_registry" )
2018-01-24 12:06:07 -05:00
} )
2018-01-11 01:41:45 -05:00
2019-12-09 03:09:29 -05:00
// numberOfSampleResources returns the number of resources advertised by a node.
func numberOfSampleResources ( node * v1 . Node ) int64 {
val , ok := node . Status . Capacity [ sampleResourceName ]
if ! ok {
return 0
}
return val . Value ( )
}
// getSampleDevicePluginPod returns the Device Plugin pod for sample resources in e2e tests.
func getSampleDevicePluginPod ( ) * v1 . Pod {
ds := readDaemonSetV1OrDie ( testfiles . ReadOrDie ( sampleDevicePluginDSYAML ) )
p := & v1 . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : sampleDevicePluginName ,
Namespace : metav1 . NamespaceSystem ,
} ,
Spec : ds . Spec . Template . Spec ,
}
return p
}
// readDaemonSetV1OrDie reads daemonset object from bytes. Panics on error.
func readDaemonSetV1OrDie ( objBytes [ ] byte ) * appsv1 . DaemonSet {
appsv1 . AddToScheme ( appsScheme )
requiredObj , err := runtime . Decode ( appsCodecs . UniversalDecoder ( appsv1 . SchemeGroupVersion ) , objBytes )
if err != nil {
panic ( err )
}
return requiredObj . ( * appsv1 . DaemonSet )
}
2019-03-12 15:58:23 -04:00
func testDevicePlugin ( f * framework . Framework , pluginSockDir string ) {
2018-12-05 02:26:15 -05:00
pluginSockDir = filepath . Join ( pluginSockDir ) + "/"
2019-07-28 00:49:36 -04:00
ginkgo . Context ( "DevicePlugin" , func ( ) {
ginkgo . By ( "Enabling support for Kubelet Plugins Watcher" )
2018-01-24 12:06:07 -05:00
tempSetCurrentKubeletConfig ( f , func ( initialConfig * kubeletconfig . KubeletConfiguration ) {
2018-11-13 22:25:56 -05:00
if initialConfig . FeatureGates == nil {
initialConfig . FeatureGates = map [ string ] bool { }
}
initialConfig . FeatureGates [ string ( features . KubeletPodResources ) ] = true
2018-01-24 12:06:07 -05:00
} )
2019-07-28 00:49:36 -04:00
ginkgo . It ( "Verifies the Kubelet device plugin functionality." , func ( ) {
ginkgo . By ( "Wait for node is ready to start with" )
2018-08-28 02:41:42 -04:00
e2enode . WaitForNodeToBeReady ( f . ClientSet , framework . TestContext . NodeName , 5 * time . Minute )
2019-12-09 03:09:29 -05:00
dp := getSampleDevicePluginPod ( )
2018-08-28 02:41:42 -04:00
for i := range dp . Spec . Containers [ 0 ] . Env {
if dp . Spec . Containers [ 0 ] . Env [ i ] . Name == envVarNamePluginSockDir {
dp . Spec . Containers [ 0 ] . Env [ i ] . Value = pluginSockDir
}
2018-01-11 01:41:45 -05:00
}
2019-08-27 05:18:43 -04:00
framework . Logf ( "env %v" , dp . Spec . Containers [ 0 ] . Env )
2018-08-28 02:41:42 -04:00
dp . Spec . NodeName = framework . TestContext . NodeName
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Create sample device plugin pod" )
2020-02-08 12:30:21 -05:00
devicePluginPod , err := f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Create ( context . TODO ( ) , dp , metav1 . CreateOptions { } )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Waiting for devices to become available on the local node" )
gomega . Eventually ( func ( ) bool {
2019-12-09 03:09:29 -05:00
return numberOfSampleResources ( getLocalNode ( f ) ) > 0
2019-07-28 00:49:36 -04:00
} , 5 * time . Minute , framework . Poll ) . Should ( gomega . BeTrue ( ) )
2019-08-27 05:18:43 -04:00
framework . Logf ( "Successfully created device plugin pod" )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Waiting for the resource exported by the sample device plugin to become available on the local node" )
2018-08-28 02:41:42 -04:00
// TODO(vikasc): Instead of hard-coding number of devices, provide number of devices in the sample-device-plugin using configmap
// and then use the same here
devsLen := int64 ( 2 )
2019-07-28 00:49:36 -04:00
gomega . Eventually ( func ( ) bool {
2020-02-07 21:16:47 -05:00
node , err := f . ClientSet . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , framework . TestContext . NodeName , metav1 . GetOptions { } )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-04-25 03:44:27 -04:00
return numberOfDevicesCapacity ( node , resourceName ) == devsLen &&
numberOfDevicesAllocatable ( node , resourceName ) == devsLen
2019-07-28 00:49:36 -04:00
} , 30 * time . Second , framework . Poll ) . Should ( gomega . BeTrue ( ) )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Creating one pod on node with at least one fake-device" )
2018-01-11 01:41:45 -05:00
podRECMD := "devs=$(ls /tmp/ | egrep '^Dev-[0-9]+$') && echo stub devices: $devs"
pod1 := f . PodClient ( ) . CreateSync ( makeBusyboxPod ( resourceName , podRECMD ) )
deviceIDRE := "stub devices: (Dev-[0-9]+)"
2019-11-06 22:59:05 -05:00
devID1 := parseLog ( f , pod1 . Name , pod1 . Name , deviceIDRE )
2019-12-04 21:14:13 -05:00
gomega . Expect ( devID1 ) . To ( gomega . Not ( gomega . Equal ( "" ) ) )
2018-01-11 01:41:45 -05:00
2018-11-13 22:25:56 -05:00
podResources , err := getNodeDevices ( )
2019-07-01 12:55:04 -04:00
var resourcesForOurPod * kubeletpodresourcesv1alpha1 . PodResources
2019-08-27 05:18:43 -04:00
framework . Logf ( "pod resources %v" , podResources )
2019-12-04 22:01:32 -05:00
framework . ExpectNoError ( err )
2019-07-31 00:31:31 -04:00
framework . ExpectEqual ( len ( podResources . PodResources ) , 2 )
2018-08-28 02:41:42 -04:00
for _ , res := range podResources . GetPodResources ( ) {
if res . Name == pod1 . Name {
resourcesForOurPod = res
}
}
2019-08-27 05:18:43 -04:00
framework . Logf ( "resourcesForOurPod %v" , resourcesForOurPod )
2019-12-04 21:14:13 -05:00
gomega . Expect ( resourcesForOurPod ) . NotTo ( gomega . BeNil ( ) )
2019-07-31 00:31:31 -04:00
framework . ExpectEqual ( resourcesForOurPod . Name , pod1 . Name )
framework . ExpectEqual ( resourcesForOurPod . Namespace , pod1 . Namespace )
framework . ExpectEqual ( len ( resourcesForOurPod . Containers ) , 1 )
framework . ExpectEqual ( resourcesForOurPod . Containers [ 0 ] . Name , pod1 . Spec . Containers [ 0 ] . Name )
framework . ExpectEqual ( len ( resourcesForOurPod . Containers [ 0 ] . Devices ) , 1 )
framework . ExpectEqual ( resourcesForOurPod . Containers [ 0 ] . Devices [ 0 ] . ResourceName , resourceName )
framework . ExpectEqual ( len ( resourcesForOurPod . Containers [ 0 ] . Devices [ 0 ] . DeviceIds ) , 1 )
2018-11-13 22:25:56 -05:00
2020-02-07 21:16:47 -05:00
pod1 , err = f . PodClient ( ) . Get ( context . TODO ( ) , pod1 . Name , metav1 . GetOptions { } )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-04-25 03:44:27 -04:00
ensurePodContainerRestart ( f , pod1 . Name , pod1 . Name )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Confirming that device assignment persists even after container restart" )
2019-11-06 22:59:05 -05:00
devIDAfterRestart := parseLog ( f , pod1 . Name , pod1 . Name , deviceIDRE )
framework . ExpectEqual ( devIDAfterRestart , devID1 )
2018-04-25 03:44:27 -04:00
2018-08-24 13:29:10 -04:00
restartTime := time . Now ( )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Restarting Kubelet" )
2018-01-11 01:41:45 -05:00
restartKubelet ( )
2018-08-24 13:29:10 -04:00
// We need to wait for node to be ready before re-registering stub device plugin.
// Otherwise, Kubelet DeviceManager may remove the re-registered sockets after it starts.
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Wait for node is ready" )
gomega . Eventually ( func ( ) bool {
2020-02-07 21:16:47 -05:00
node , err := f . ClientSet . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , framework . TestContext . NodeName , metav1 . GetOptions { } )
2018-08-24 13:29:10 -04:00
framework . ExpectNoError ( err )
for _ , cond := range node . Status . Conditions {
if cond . Type == v1 . NodeReady && cond . Status == v1 . ConditionTrue && cond . LastHeartbeatTime . After ( restartTime ) {
return true
}
}
return false
2019-07-28 00:49:36 -04:00
} , 5 * time . Minute , framework . Poll ) . Should ( gomega . BeTrue ( ) )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Re-Register resources and deleting the pods and waiting for container removal" )
2018-08-28 02:41:42 -04:00
getOptions := metav1 . GetOptions { }
gp := int64 ( 0 )
deleteOptions := metav1 . DeleteOptions {
GracePeriodSeconds : & gp ,
}
2020-02-07 21:16:47 -05:00
err = f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Delete ( context . TODO ( ) , dp . Name , & deleteOptions )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-08-28 02:41:42 -04:00
waitForContainerRemoval ( devicePluginPod . Spec . Containers [ 0 ] . Name , devicePluginPod . Name , devicePluginPod . Namespace )
2020-02-07 21:16:47 -05:00
_ , err = f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Get ( context . TODO ( ) , dp . Name , getOptions )
2019-08-27 05:18:43 -04:00
framework . Logf ( "Trying to get dp pod after deletion. err must be non-nil. err: %v" , err )
2018-08-28 02:41:42 -04:00
framework . ExpectError ( err )
2018-01-11 01:41:45 -05:00
2020-02-08 12:30:21 -05:00
devicePluginPod , err = f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Create ( context . TODO ( ) , dp , metav1 . CreateOptions { } )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-08-24 13:29:10 -04:00
ensurePodContainerRestart ( f , pod1 . Name , pod1 . Name )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Confirming that after a kubelet restart, fake-device assignement is kept" )
2019-11-06 22:59:05 -05:00
devIDRestart1 := parseLog ( f , pod1 . Name , pod1 . Name , deviceIDRE )
framework . ExpectEqual ( devIDRestart1 , devID1 )
2018-08-24 13:29:10 -04:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Waiting for resource to become available on the local node after re-registration" )
gomega . Eventually ( func ( ) bool {
2020-02-07 21:16:47 -05:00
node , err := f . ClientSet . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , framework . TestContext . NodeName , metav1 . GetOptions { } )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-04-25 03:44:27 -04:00
return numberOfDevicesCapacity ( node , resourceName ) == devsLen &&
numberOfDevicesAllocatable ( node , resourceName ) == devsLen
2019-07-28 00:49:36 -04:00
} , 30 * time . Second , framework . Poll ) . Should ( gomega . BeTrue ( ) )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Creating another pod" )
2018-01-11 01:41:45 -05:00
pod2 := f . PodClient ( ) . CreateSync ( makeBusyboxPod ( resourceName , podRECMD ) )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Checking that pod got a different fake device" )
2019-11-06 22:59:05 -05:00
devID2 := parseLog ( f , pod2 . Name , pod2 . Name , deviceIDRE )
2018-01-11 01:41:45 -05:00
2019-12-04 21:14:13 -05:00
gomega . Expect ( devID1 ) . To ( gomega . Not ( gomega . Equal ( devID2 ) ) )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "By deleting the pods and waiting for container removal" )
2020-02-07 21:16:47 -05:00
err = f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Delete ( context . TODO ( ) , dp . Name , & deleteOptions )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-08-28 02:41:42 -04:00
waitForContainerRemoval ( devicePluginPod . Spec . Containers [ 0 ] . Name , devicePluginPod . Name , devicePluginPod . Namespace )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Waiting for stub device plugin to become unhealthy on the local node" )
gomega . Eventually ( func ( ) int64 {
2020-02-07 21:16:47 -05:00
node , err := f . ClientSet . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , framework . TestContext . NodeName , metav1 . GetOptions { } )
2018-01-11 01:41:45 -05:00
framework . ExpectNoError ( err )
2018-04-25 03:44:27 -04:00
return numberOfDevicesAllocatable ( node , resourceName )
2019-07-28 00:49:36 -04:00
} , 30 * time . Second , framework . Poll ) . Should ( gomega . Equal ( int64 ( 0 ) ) )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Checking that scheduled pods can continue to run even after we delete device plugin." )
2018-04-25 03:44:27 -04:00
ensurePodContainerRestart ( f , pod1 . Name , pod1 . Name )
2019-11-06 22:59:05 -05:00
devIDRestart1 = parseLog ( f , pod1 . Name , pod1 . Name , deviceIDRE )
framework . ExpectEqual ( devIDRestart1 , devID1 )
2018-04-25 03:44:27 -04:00
ensurePodContainerRestart ( f , pod2 . Name , pod2 . Name )
2019-11-06 22:59:05 -05:00
devIDRestart2 := parseLog ( f , pod2 . Name , pod2 . Name , deviceIDRE )
framework . ExpectEqual ( devIDRestart2 , devID2 )
2018-01-11 01:41:45 -05:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Re-register resources" )
2020-02-08 12:30:21 -05:00
devicePluginPod , err = f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Create ( context . TODO ( ) , dp , metav1 . CreateOptions { } )
2018-04-25 03:44:27 -04:00
framework . ExpectNoError ( err )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Waiting for the resource exported by the stub device plugin to become healthy on the local node" )
gomega . Eventually ( func ( ) int64 {
2020-02-07 21:16:47 -05:00
node , err := f . ClientSet . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , framework . TestContext . NodeName , metav1 . GetOptions { } )
2018-04-25 03:44:27 -04:00
framework . ExpectNoError ( err )
return numberOfDevicesAllocatable ( node , resourceName )
2019-07-28 00:49:36 -04:00
} , 30 * time . Second , framework . Poll ) . Should ( gomega . Equal ( devsLen ) )
2018-04-25 03:44:27 -04:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "by deleting the pods and waiting for container removal" )
2020-02-07 21:16:47 -05:00
err = f . ClientSet . CoreV1 ( ) . Pods ( metav1 . NamespaceSystem ) . Delete ( context . TODO ( ) , dp . Name , & deleteOptions )
2018-04-25 03:44:27 -04:00
framework . ExpectNoError ( err )
2018-08-28 02:41:42 -04:00
waitForContainerRemoval ( devicePluginPod . Spec . Containers [ 0 ] . Name , devicePluginPod . Name , devicePluginPod . Namespace )
2018-04-25 03:44:27 -04:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Waiting for stub device plugin to become unavailable on the local node" )
gomega . Eventually ( func ( ) bool {
2020-02-07 21:16:47 -05:00
node , err := f . ClientSet . CoreV1 ( ) . Nodes ( ) . Get ( context . TODO ( ) , framework . TestContext . NodeName , metav1 . GetOptions { } )
2018-04-25 03:44:27 -04:00
framework . ExpectNoError ( err )
return numberOfDevicesCapacity ( node , resourceName ) <= 0
2019-07-28 00:49:36 -04:00
} , 10 * time . Minute , framework . Poll ) . Should ( gomega . BeTrue ( ) )
2018-04-25 03:44:27 -04:00
2018-01-11 01:41:45 -05:00
// Cleanup
f . PodClient ( ) . DeleteSync ( pod1 . Name , & metav1 . DeleteOptions { } , framework . DefaultPodDeletionTimeout )
f . PodClient ( ) . DeleteSync ( pod2 . Name , & metav1 . DeleteOptions { } , framework . DefaultPodDeletionTimeout )
} )
} )
2018-01-24 12:06:07 -05:00
}
2018-01-11 01:41:45 -05:00
// makeBusyboxPod returns a simple Pod spec with a busybox container
2017-12-29 05:43:38 -05:00
// that requests resourceName and runs the specified command.
func makeBusyboxPod ( resourceName , cmd string ) * v1 . Pod {
podName := "device-plugin-test-" + string ( uuid . NewUUID ( ) )
rl := v1 . ResourceList { v1 . ResourceName ( resourceName ) : * resource . NewQuantity ( 1 , resource . DecimalSI ) }
return & v1 . Pod {
ObjectMeta : metav1 . ObjectMeta { Name : podName } ,
Spec : v1 . PodSpec {
RestartPolicy : v1 . RestartPolicyAlways ,
Containers : [ ] v1 . Container { {
Image : busyboxImage ,
Name : podName ,
// Runs the specified command in the test pod.
Command : [ ] string { "sh" , "-c" , cmd } ,
Resources : v1 . ResourceRequirements {
Limits : rl ,
Requests : rl ,
} ,
} } ,
} ,
}
}
2018-04-25 03:44:27 -04:00
// ensurePodContainerRestart confirms that pod container has restarted at least once
func ensurePodContainerRestart ( f * framework . Framework , podName string , contName string ) {
var initialCount int32
var currentCount int32
2020-02-07 21:16:47 -05:00
p , err := f . PodClient ( ) . Get ( context . TODO ( ) , podName , metav1 . GetOptions { } )
2018-04-25 03:44:27 -04:00
if err != nil || len ( p . Status . ContainerStatuses ) < 1 {
2019-08-27 05:18:43 -04:00
framework . Failf ( "ensurePodContainerRestart failed for pod %q: %v" , podName , err )
2018-04-25 03:44:27 -04:00
}
initialCount = p . Status . ContainerStatuses [ 0 ] . RestartCount
2019-07-28 00:49:36 -04:00
gomega . Eventually ( func ( ) bool {
2020-02-07 21:16:47 -05:00
p , err = f . PodClient ( ) . Get ( context . TODO ( ) , podName , metav1 . GetOptions { } )
2017-12-29 05:43:38 -05:00
if err != nil || len ( p . Status . ContainerStatuses ) < 1 {
return false
}
2018-04-25 03:44:27 -04:00
currentCount = p . Status . ContainerStatuses [ 0 ] . RestartCount
2019-08-27 05:18:43 -04:00
framework . Logf ( "initial %v, current %v" , initialCount , currentCount )
2018-04-25 03:44:27 -04:00
return currentCount > initialCount
2019-07-28 00:49:36 -04:00
} , 5 * time . Minute , framework . Poll ) . Should ( gomega . BeTrue ( ) )
2018-04-25 03:44:27 -04:00
}
2018-01-11 01:41:45 -05:00
2018-04-25 03:44:27 -04:00
// parseLog returns the matching string for the specified regular expression parsed from the container logs.
func parseLog ( f * framework . Framework , podName string , contName string , re string ) string {
2019-05-07 20:09:50 -04:00
logs , err := e2epod . GetPodLogs ( f . ClientSet , f . Namespace . Name , podName , contName )
2017-12-29 05:43:38 -05:00
if err != nil {
2019-08-27 05:18:43 -04:00
framework . Failf ( "GetPodLogs for pod %q failed: %v" , podName , err )
2017-12-29 05:43:38 -05:00
}
2018-01-11 01:41:45 -05:00
2019-08-27 05:18:43 -04:00
framework . Logf ( "got pod logs: %v" , logs )
2017-12-29 05:43:38 -05:00
regex := regexp . MustCompile ( re )
matches := regex . FindStringSubmatch ( logs )
if len ( matches ) < 2 {
2018-04-25 03:44:27 -04:00
return ""
2017-12-29 05:43:38 -05:00
}
2018-01-11 01:41:45 -05:00
2018-04-25 03:44:27 -04:00
return matches [ 1 ]
2017-12-29 05:43:38 -05:00
}
2018-04-25 03:44:27 -04:00
// numberOfDevicesCapacity returns the number of devices of resourceName advertised by a node capacity
func numberOfDevicesCapacity ( node * v1 . Node , resourceName string ) int64 {
2017-12-29 05:43:38 -05:00
val , ok := node . Status . Capacity [ v1 . ResourceName ( resourceName ) ]
if ! ok {
return 0
}
return val . Value ( )
}
2018-01-11 01:41:45 -05:00
2018-04-25 03:44:27 -04:00
// numberOfDevicesAllocatable returns the number of devices of resourceName advertised by a node allocatable
func numberOfDevicesAllocatable ( node * v1 . Node , resourceName string ) int64 {
val , ok := node . Status . Allocatable [ v1 . ResourceName ( resourceName ) ]
if ! ok {
return 0
}
return val . Value ( )
}