2021-08-12 17:13:11 -04:00
//go:build cgo && linux
2017-03-14 12:45:05 -04:00
2016-06-01 15:57:32 -04:00
/ *
2016-06-02 20:25:58 -04:00
Copyright 2016 The Kubernetes Authors .
2016-06-01 15:57:32 -04: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 .
* /
2019-11-06 22:59:05 -05:00
package e2enode
2016-06-01 15:57:32 -04:00
import (
2020-01-27 21:19:44 -05:00
"context"
2016-06-01 15:57:32 -04:00
"fmt"
2017-02-18 01:54:52 -05:00
"os"
"path"
2016-06-01 15:57:32 -04:00
"time"
2022-03-29 02:12:12 -04:00
"github.com/onsi/ginkgo/v2"
2020-10-30 10:32:10 -04:00
"github.com/onsi/gomega"
2020-01-27 21:19:44 -05:00
v1 "k8s.io/api/core/v1"
2017-01-11 09:09:48 -05:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2017-01-19 09:50:16 -05:00
"k8s.io/apimachinery/pkg/fields"
2017-01-16 15:13:59 -05:00
"k8s.io/apimachinery/pkg/types"
2017-01-24 09:35:22 -05:00
"k8s.io/apimachinery/pkg/util/uuid"
2017-06-23 16:56:37 -04:00
clientset "k8s.io/client-go/kubernetes"
coreclientset "k8s.io/client-go/kubernetes/typed/core/v1"
2022-04-04 08:00:06 -04:00
admissionapi "k8s.io/pod-security-admission/api"
2020-10-30 10:32:10 -04:00
2018-12-05 18:07:52 -05:00
"k8s.io/kubernetes/pkg/kubelet/util"
2024-12-11 16:11:51 -05:00
"k8s.io/kubernetes/test/e2e/feature"
2016-06-01 15:57:32 -04:00
"k8s.io/kubernetes/test/e2e/framework"
2019-05-07 20:09:50 -04:00
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
2019-02-26 14:05:32 -05:00
testutils "k8s.io/kubernetes/test/utils"
2016-06-01 15:57:32 -04:00
)
2024-12-11 16:11:51 -05:00
var _ = SIGDescribe ( "NodeProblemDetector" , feature . NodeProblemDetector , framework . WithSerial ( ) , func ( ) {
2016-06-01 15:57:32 -04:00
const (
pollInterval = 1 * time . Second
pollConsistent = 5 * time . Second
2023-08-29 05:22:28 -04:00
pollTimeout = 5 * time . Minute
2016-06-01 15:57:32 -04:00
)
f := framework . NewDefaultFramework ( "node-problem-detector" )
2023-05-10 09:38:10 -04:00
f . NamespacePodSecurityLevel = admissionapi . LevelPrivileged
2016-10-18 09:00:38 -04:00
var c clientset . Interface
2016-06-01 15:57:32 -04:00
var uid string
var ns , name , configName , eventNamespace string
2017-02-06 15:12:31 -05:00
var bootTime , nodeTime time . Time
2019-02-07 18:41:16 -05:00
var image string
2019-07-28 00:49:36 -04:00
ginkgo . BeforeEach ( func ( ) {
2016-10-18 09:00:38 -04:00
c = f . ClientSet
2016-06-01 15:57:32 -04:00
ns = f . Namespace . Name
2016-07-26 11:13:18 -04:00
uid = string ( uuid . NewUUID ( ) )
2016-06-01 15:57:32 -04:00
name = "node-problem-detector-" + uid
configName = "node-problem-detector-config-" + uid
// There is no namespace for Node, event recorder will set default namespace for node events.
2017-01-21 22:36:02 -05:00
eventNamespace = metav1 . NamespaceDefault
2019-02-07 18:41:16 -05:00
image = getNodeProblemDetectorImage ( )
2019-07-28 00:49:36 -04:00
ginkgo . By ( fmt . Sprintf ( "Using node-problem-detector image: %s" , image ) )
2016-06-01 15:57:32 -04:00
} )
2017-02-06 15:12:31 -05:00
// Test system log monitor. We may add other tests if we have more problem daemons in the future.
2021-02-22 13:53:33 -05:00
ginkgo . Describe ( "SystemLogMonitor" , func ( ) {
2016-06-01 15:57:32 -04:00
const (
2017-02-18 01:54:52 -05:00
// Use test condition to avoid changing the real node condition in use.
2018-02-09 01:53:53 -05:00
// TODO(random-liu): Now node condition could be arbitrary string, consider whether we need to
2016-06-01 15:57:32 -04:00
// add TestCondition when switching to predefined condition list.
2017-02-18 01:54:52 -05:00
condition = v1 . NodeConditionType ( "TestCondition" )
2016-11-03 00:21:11 -04:00
// File paths used in the test.
2020-11-05 07:35:02 -05:00
logFile = "/log/test.log"
configFile = "/config/testconfig.json"
kubeConfigFile = "/config/kubeconfig"
etcLocaltime = "/etc/localtime"
2016-11-03 00:21:11 -04:00
// Volumes used in the test.
configVolume = "config"
logVolume = "log"
localtimeVolume = "localtime"
// Reasons and messages used in the test.
2016-06-01 15:57:32 -04:00
defaultReason = "Default"
defaultMessage = "default message"
tempReason = "Temporary"
tempMessage = "temporary error"
2017-02-06 15:12:31 -05:00
permReason1 = "Permanent1"
permMessage1 = "permanent error 1"
permReason2 = "Permanent2"
permMessage2 = "permanent error 2"
2016-06-01 15:57:32 -04:00
)
2017-03-20 17:18:18 -04:00
var source , config , hostLogFile string
2017-02-06 15:12:31 -05:00
var lookback time . Duration
2017-01-21 22:36:02 -05:00
var eventListOptions metav1 . ListOptions
2016-06-01 15:57:32 -04:00
2022-12-12 04:11:10 -05:00
ginkgo . BeforeEach ( func ( ctx context . Context ) {
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Calculate Lookback duration" )
2017-02-18 01:54:52 -05:00
var err error
2018-12-05 18:07:52 -05:00
nodeTime = time . Now ( )
bootTime , err = util . GetBootTime ( )
2019-12-04 22:01:32 -05:00
framework . ExpectNoError ( err )
2018-12-05 18:07:52 -05:00
2017-02-06 15:12:31 -05:00
// Set lookback duration longer than node up time.
// Assume the test won't take more than 1 hour, in fact it usually only takes 90 seconds.
lookback = nodeTime . Sub ( bootTime ) + time . Hour
2017-02-18 01:54:52 -05:00
// Randomize the source name
2016-06-01 15:57:32 -04:00
source = "kernel-monitor-" + uid
config = `
{
2017-02-06 15:12:31 -05:00
"plugin" : "filelog" ,
"pluginConfig" : {
"timestamp" : "^.{15}" ,
"message" : "kernel: \\[.*\\] (.*)" ,
"timestampFormat" : "` + time.Stamp + `"
} ,
2017-02-18 01:54:52 -05:00
"logPath" : "` + logFile + `" ,
2016-11-03 00:21:11 -04:00
"lookback" : "` + lookback.String() + `" ,
2016-06-01 15:57:32 -04:00
"bufferSize" : 10 ,
"source" : "` + source + `" ,
"conditions" : [
{
"type" : "` + string(condition) + `" ,
"reason" : "` + defaultReason + `" ,
"message" : "` + defaultMessage + `"
}
] ,
"rules" : [
{
"type" : "temporary" ,
"reason" : "` + tempReason + `" ,
"pattern" : "` + tempMessage + `"
} ,
{
"type" : "permanent" ,
"condition" : "` + string(condition) + `" ,
2017-02-06 15:12:31 -05:00
"reason" : "` + permReason1 + `" ,
"pattern" : "` + permMessage1 + " . * " + `"
} ,
{
"type" : "permanent" ,
"condition" : "` + string(condition) + `" ,
"reason" : "` + permReason2 + `" ,
"pattern" : "` + permMessage2 + " . * " + `"
2016-06-01 15:57:32 -04:00
}
]
} `
2020-10-30 10:32:10 -04:00
2020-11-05 07:35:02 -05:00
// This token is known to apiserver and its group is `system:masters`.
// See also the function `generateTokenFile` in `test/e2e_node/services/apiserver.go`.
kubeConfig := fmt . Sprintf ( `
apiVersion : v1
kind : Config
users :
- name : node - problem - detector
user :
token : % s
clusters :
- cluster :
server : % s
insecure - skip - tls - verify : true
name : local
contexts :
- context :
cluster : local
user : node - problem - detector
name : local - context
current - context : local - context
` , framework . TestContext . BearerToken , framework . TestContext . Host )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Generate event list options" )
2016-06-01 15:57:32 -04:00
selector := fields . Set {
"involvedObject.kind" : "Node" ,
2017-02-18 01:54:52 -05:00
"involvedObject.name" : framework . TestContext . NodeName ,
2017-01-21 22:36:02 -05:00
"involvedObject.namespace" : metav1 . NamespaceAll ,
2016-06-01 15:57:32 -04:00
"source" : source ,
2016-11-18 15:55:17 -05:00
} . AsSelector ( ) . String ( )
2017-01-21 22:36:02 -05:00
eventListOptions = metav1 . ListOptions { FieldSelector : selector }
2020-10-30 10:32:10 -04:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Create config map for the node problem detector" )
2022-12-12 04:11:10 -05:00
_ , err = c . CoreV1 ( ) . ConfigMaps ( ns ) . Create ( ctx , & v1 . ConfigMap {
2017-02-18 01:54:52 -05:00
ObjectMeta : metav1 . ObjectMeta { Name : configName } ,
2020-11-05 07:35:02 -05:00
Data : map [ string ] string {
path . Base ( configFile ) : config ,
path . Base ( kubeConfigFile ) : kubeConfig ,
2020-10-30 10:32:10 -04:00
} ,
} , metav1 . CreateOptions { } )
framework . ExpectNoError ( err )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Create the node problem detector" )
2017-06-18 05:51:10 -04:00
hostPathType := new ( v1 . HostPathType )
2020-10-30 10:32:10 -04:00
* hostPathType = v1 . HostPathFileOrCreate
2022-12-12 04:11:10 -05:00
pod := e2epod . NewPodClient ( f ) . CreateSync ( ctx , & v1 . Pod {
2017-01-16 22:38:19 -05:00
ObjectMeta : metav1 . ObjectMeta {
2016-06-01 15:57:32 -04:00
Name : name ,
} ,
2016-11-18 15:55:17 -05:00
Spec : v1 . PodSpec {
2020-10-30 10:32:10 -04:00
HostNetwork : true ,
SecurityContext : & v1 . PodSecurityContext { } ,
ServiceAccountName : name ,
2016-11-18 15:55:17 -05:00
Volumes : [ ] v1 . Volume {
2016-06-01 15:57:32 -04:00
{
Name : configVolume ,
2016-11-18 15:55:17 -05:00
VolumeSource : v1 . VolumeSource {
ConfigMap : & v1 . ConfigMapVolumeSource {
LocalObjectReference : v1 . LocalObjectReference { Name : configName } ,
2016-06-01 15:57:32 -04:00
} ,
} ,
} ,
{
Name : logVolume ,
2016-11-18 15:55:17 -05:00
VolumeSource : v1 . VolumeSource {
2017-03-20 17:18:18 -04:00
EmptyDir : & v1 . EmptyDirVolumeSource { } ,
2016-06-01 15:57:32 -04:00
} ,
} ,
2016-11-03 00:21:11 -04:00
{
Name : localtimeVolume ,
2016-11-18 15:55:17 -05:00
VolumeSource : v1 . VolumeSource {
2017-06-18 05:51:10 -04:00
HostPath : & v1 . HostPathVolumeSource {
Path : etcLocaltime ,
Type : hostPathType ,
} ,
2016-11-03 00:21:11 -04:00
} ,
} ,
2016-06-01 15:57:32 -04:00
} ,
2020-11-09 13:58:09 -05:00
InitContainers : [ ] v1 . Container {
{
Name : "init-log-file" ,
Image : "debian" ,
Command : [ ] string { "/bin/sh" } ,
Args : [ ] string {
"-c" ,
fmt . Sprintf ( "touch %s" , logFile ) ,
} ,
VolumeMounts : [ ] v1 . VolumeMount {
{
Name : logVolume ,
MountPath : path . Dir ( logFile ) ,
} ,
{
Name : localtimeVolume ,
MountPath : etcLocaltime ,
} ,
} ,
} ,
} ,
2016-11-18 15:55:17 -05:00
Containers : [ ] v1 . Container {
2016-06-01 15:57:32 -04:00
{
2017-02-18 01:54:52 -05:00
Name : name ,
Image : image ,
2020-11-09 13:58:09 -05:00
Command : [ ] string { "/node-problem-detector" } ,
Args : [ ] string {
"--logtostderr" ,
fmt . Sprintf ( "--system-log-monitors=%s" , configFile ) ,
2020-11-05 07:35:02 -05:00
// `ServiceAccount` admission controller is disabled in node e2e tests, so we could not use
// inClusterConfig here.
fmt . Sprintf ( "--apiserver-override=%s?inClusterConfig=false&auth=%s" , framework . TestContext . Host , kubeConfigFile ) ,
2020-11-09 13:58:09 -05:00
} ,
2016-11-18 15:55:17 -05:00
Env : [ ] v1 . EnvVar {
2016-11-03 00:21:11 -04:00
{
Name : "NODE_NAME" ,
2016-11-18 15:55:17 -05:00
ValueFrom : & v1 . EnvVarSource {
FieldRef : & v1 . ObjectFieldSelector {
2016-11-03 00:21:11 -04:00
APIVersion : "v1" ,
FieldPath : "spec.nodeName" ,
} ,
} ,
} ,
} ,
2016-11-18 15:55:17 -05:00
VolumeMounts : [ ] v1 . VolumeMount {
2016-06-01 15:57:32 -04:00
{
Name : logVolume ,
2017-02-18 01:54:52 -05:00
MountPath : path . Dir ( logFile ) ,
2016-06-01 15:57:32 -04:00
} ,
2016-11-03 00:21:11 -04:00
{
Name : localtimeVolume ,
MountPath : etcLocaltime ,
} ,
2016-06-01 15:57:32 -04:00
{
Name : configVolume ,
2017-02-18 01:54:52 -05:00
MountPath : path . Dir ( configFile ) ,
2016-06-01 15:57:32 -04:00
} ,
} ,
} ,
} ,
} ,
} )
2017-03-20 17:18:18 -04:00
// TODO: remove hardcoded kubelet volume directory path
// framework.TestContext.KubeVolumeDir is currently not populated for node e2e
hostLogFile = "/var/lib/kubelet/pods/" + string ( pod . UID ) + "/volumes/kubernetes.io~empty-dir" + logFile
2016-06-01 15:57:32 -04:00
} )
2022-10-17 08:47:15 -04:00
ginkgo . It ( "should generate node condition and events for corresponding errors" , func ( ctx context . Context ) {
2016-11-03 00:21:11 -04:00
for _ , test := range [ ] struct {
description string
timestamp time . Time
message string
messageNum int
2019-02-07 18:41:16 -05:00
tempEvents int // Events for temp errors
totalEvents int // Events for both temp errors and condition changes
2016-11-03 00:21:11 -04:00
conditionReason string
conditionMessage string
2016-11-18 15:55:17 -05:00
conditionType v1 . ConditionStatus
2016-11-03 00:21:11 -04:00
} {
{
description : "should generate default node condition" ,
conditionReason : defaultReason ,
conditionMessage : defaultMessage ,
2016-11-18 15:55:17 -05:00
conditionType : v1 . ConditionFalse ,
2016-11-03 00:21:11 -04:00
} ,
{
description : "should not generate events for too old log" ,
2017-02-06 15:12:31 -05:00
timestamp : bootTime . Add ( - 1 * time . Minute ) ,
2016-11-03 00:21:11 -04:00
message : tempMessage ,
messageNum : 3 ,
conditionReason : defaultReason ,
conditionMessage : defaultMessage ,
2016-11-18 15:55:17 -05:00
conditionType : v1 . ConditionFalse ,
2016-11-03 00:21:11 -04:00
} ,
{
description : "should not change node condition for too old log" ,
2017-02-06 15:12:31 -05:00
timestamp : bootTime . Add ( - 1 * time . Minute ) ,
message : permMessage1 ,
2016-11-03 00:21:11 -04:00
messageNum : 1 ,
conditionReason : defaultReason ,
conditionMessage : defaultMessage ,
2016-11-18 15:55:17 -05:00
conditionType : v1 . ConditionFalse ,
2016-11-03 00:21:11 -04:00
} ,
{
description : "should generate event for old log within lookback duration" ,
2017-02-06 15:12:31 -05:00
timestamp : nodeTime ,
2016-11-03 00:21:11 -04:00
message : tempMessage ,
messageNum : 3 ,
2019-02-07 18:41:16 -05:00
tempEvents : 3 ,
totalEvents : 3 ,
2016-11-03 00:21:11 -04:00
conditionReason : defaultReason ,
conditionMessage : defaultMessage ,
2016-11-18 15:55:17 -05:00
conditionType : v1 . ConditionFalse ,
2016-11-03 00:21:11 -04:00
} ,
{
description : "should change node condition for old log within lookback duration" ,
timestamp : nodeTime ,
2017-02-06 15:12:31 -05:00
message : permMessage1 ,
2016-11-03 00:21:11 -04:00
messageNum : 1 ,
2019-02-07 18:41:16 -05:00
tempEvents : 3 , // event number for temp errors should not change
totalEvents : 4 , // add 1 event for condition change
2017-02-06 15:12:31 -05:00
conditionReason : permReason1 ,
conditionMessage : permMessage1 ,
conditionType : v1 . ConditionTrue ,
2016-11-03 00:21:11 -04:00
} ,
{
description : "should generate event for new log" ,
timestamp : nodeTime . Add ( 5 * time . Minute ) ,
message : tempMessage ,
messageNum : 3 ,
2019-02-07 18:41:16 -05:00
tempEvents : 6 , // add 3 events for temp errors
totalEvents : 7 , // add 3 events for temp errors
2017-02-06 15:12:31 -05:00
conditionReason : permReason1 ,
conditionMessage : permMessage1 ,
conditionType : v1 . ConditionTrue ,
} ,
{
description : "should not update node condition with the same reason" ,
timestamp : nodeTime . Add ( 5 * time . Minute ) ,
message : permMessage1 + "different message" ,
messageNum : 1 ,
2019-02-07 18:41:16 -05:00
tempEvents : 6 , // event number should not change
totalEvents : 7 , // event number should not change
2017-02-06 15:12:31 -05:00
conditionReason : permReason1 ,
conditionMessage : permMessage1 ,
conditionType : v1 . ConditionTrue ,
2016-11-03 00:21:11 -04:00
} ,
{
description : "should change node condition for new log" ,
timestamp : nodeTime . Add ( 5 * time . Minute ) ,
2017-02-06 15:12:31 -05:00
message : permMessage2 ,
2016-11-03 00:21:11 -04:00
messageNum : 1 ,
2019-02-07 18:41:16 -05:00
tempEvents : 6 , // event number for temp errors should not change
totalEvents : 8 , // add 1 event for condition change
2017-02-06 15:12:31 -05:00
conditionReason : permReason2 ,
conditionMessage : permMessage2 ,
2016-11-18 15:55:17 -05:00
conditionType : v1 . ConditionTrue ,
2016-11-03 00:21:11 -04:00
} ,
} {
2019-07-28 00:49:36 -04:00
ginkgo . By ( test . description )
2016-11-03 00:21:11 -04:00
if test . messageNum > 0 {
2019-07-28 00:49:36 -04:00
ginkgo . By ( fmt . Sprintf ( "Inject %d logs: %q" , test . messageNum , test . message ) )
2017-03-20 17:18:18 -04:00
err := injectLog ( hostLogFile , test . timestamp , test . message , test . messageNum )
2019-06-08 13:44:08 -04:00
framework . ExpectNoError ( err )
2016-11-03 00:21:11 -04:00
}
2019-07-28 00:49:36 -04:00
ginkgo . By ( fmt . Sprintf ( "Wait for %d temp events generated" , test . tempEvents ) )
2022-12-12 04:11:10 -05:00
gomega . Eventually ( ctx , func ( ctx context . Context ) error {
return verifyEvents ( ctx , c . CoreV1 ( ) . Events ( eventNamespace ) , eventListOptions , test . tempEvents , tempReason , tempMessage )
2019-07-28 00:49:36 -04:00
} , pollTimeout , pollInterval ) . Should ( gomega . Succeed ( ) )
ginkgo . By ( fmt . Sprintf ( "Wait for %d total events generated" , test . totalEvents ) )
2022-12-12 04:11:10 -05:00
gomega . Eventually ( ctx , func ( ctx context . Context ) error {
return verifyTotalEvents ( ctx , c . CoreV1 ( ) . Events ( eventNamespace ) , eventListOptions , test . totalEvents )
2019-07-28 00:49:36 -04:00
} , pollTimeout , pollInterval ) . Should ( gomega . Succeed ( ) )
ginkgo . By ( fmt . Sprintf ( "Make sure only %d total events generated" , test . totalEvents ) )
2022-12-12 04:11:10 -05:00
gomega . Consistently ( ctx , func ( ctx context . Context ) error {
return verifyTotalEvents ( ctx , c . CoreV1 ( ) . Events ( eventNamespace ) , eventListOptions , test . totalEvents )
2019-07-28 00:49:36 -04:00
} , pollConsistent , pollInterval ) . Should ( gomega . Succeed ( ) )
2016-11-03 00:21:11 -04:00
2019-07-28 00:49:36 -04:00
ginkgo . By ( fmt . Sprintf ( "Make sure node condition %q is set" , condition ) )
2022-12-12 04:11:10 -05:00
gomega . Eventually ( ctx , func ( ctx context . Context ) error {
return verifyNodeCondition ( ctx , c . CoreV1 ( ) . Nodes ( ) , condition , test . conditionType , test . conditionReason , test . conditionMessage )
2019-07-28 00:49:36 -04:00
} , pollTimeout , pollInterval ) . Should ( gomega . Succeed ( ) )
ginkgo . By ( fmt . Sprintf ( "Make sure node condition %q is stable" , condition ) )
2022-12-12 04:11:10 -05:00
gomega . Consistently ( ctx , func ( ctx context . Context ) error {
return verifyNodeCondition ( ctx , c . CoreV1 ( ) . Nodes ( ) , condition , test . conditionType , test . conditionReason , test . conditionMessage )
2019-07-28 00:49:36 -04:00
} , pollConsistent , pollInterval ) . Should ( gomega . Succeed ( ) )
2016-11-03 00:21:11 -04:00
}
2016-06-01 15:57:32 -04:00
} )
2022-12-12 04:11:10 -05:00
ginkgo . AfterEach ( func ( ctx context . Context ) {
2022-04-24 04:55:25 -04:00
if ginkgo . CurrentSpecReport ( ) . Failed ( ) && framework . TestContext . DumpLogsOnFailure {
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Get node problem detector log" )
2022-12-12 04:11:10 -05:00
log , err := e2epod . GetPodLogs ( ctx , c , ns , name , name )
2019-07-28 00:49:36 -04:00
gomega . Expect ( err ) . ShouldNot ( gomega . HaveOccurred ( ) )
2019-08-27 05:18:43 -04:00
framework . Logf ( "Node Problem Detector logs:\n %s" , log )
2016-11-03 00:21:11 -04:00
}
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Delete the node problem detector" )
2022-12-12 04:11:10 -05:00
framework . ExpectNoError ( e2epod . NewPodClient ( f ) . Delete ( ctx , name , * metav1 . NewDeleteOptions ( 0 ) ) )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Wait for the node problem detector to disappear" )
2023-01-20 06:45:01 -05:00
gomega . Expect ( e2epod . WaitForPodNotFoundInNamespace ( ctx , c , name , ns , pollTimeout ) ) . To ( gomega . Succeed ( ) )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Delete the config map" )
2022-12-12 04:11:10 -05:00
framework . ExpectNoError ( c . CoreV1 ( ) . ConfigMaps ( ns ) . Delete ( ctx , configName , metav1 . DeleteOptions { } ) )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Clean up the events" )
2022-12-12 04:11:10 -05:00
gomega . Expect ( c . CoreV1 ( ) . Events ( eventNamespace ) . DeleteCollection ( ctx , * metav1 . NewDeleteOptions ( 0 ) , eventListOptions ) ) . To ( gomega . Succeed ( ) )
2019-07-28 00:49:36 -04:00
ginkgo . By ( "Clean up the node condition" )
2016-06-01 15:57:32 -04:00
patch := [ ] byte ( fmt . Sprintf ( ` { "status": { "conditions":[ { "$patch":"delete","type":"%s"}]}} ` , condition ) )
2022-12-12 04:11:10 -05:00
c . CoreV1 ( ) . RESTClient ( ) . Patch ( types . StrategicMergePatchType ) . Resource ( "nodes" ) . Name ( framework . TestContext . NodeName ) . SubResource ( "status" ) . Body ( patch ) . Do ( ctx )
2016-06-01 15:57:32 -04:00
} )
} )
} )
2017-02-18 01:54:52 -05:00
// injectLog injects kernel log into specified file.
func injectLog ( file string , timestamp time . Time , log string , num int ) error {
f , err := os . OpenFile ( file , os . O_RDWR | os . O_APPEND , 0666 )
2017-02-06 15:12:31 -05:00
if err != nil {
2017-02-18 01:54:52 -05:00
return err
2017-02-06 15:12:31 -05:00
}
2017-05-22 09:51:11 -04:00
defer f . Close ( )
2017-02-18 01:54:52 -05:00
for i := 0 ; i < num ; i ++ {
_ , err := f . WriteString ( fmt . Sprintf ( "%s kernel: [0.000000] %s\n" , timestamp . Format ( time . Stamp ) , log ) )
if err != nil {
return err
}
2017-02-06 15:12:31 -05:00
}
2017-02-18 01:54:52 -05:00
return nil
}
2019-02-07 18:41:16 -05:00
// verifyEvents verifies there are num specific events generated with given reason and message.
2022-12-12 04:11:10 -05:00
func verifyEvents ( ctx context . Context , e coreclientset . EventInterface , options metav1 . ListOptions , num int , reason , message string ) error {
events , err := e . List ( ctx , options )
2016-06-01 15:57:32 -04:00
if err != nil {
return err
}
count := 0
for _ , event := range events . Items {
if event . Reason != reason || event . Message != message {
2019-02-07 18:41:16 -05:00
continue
2016-06-01 15:57:32 -04:00
}
count += int ( event . Count )
}
if count != num {
2020-07-08 09:31:41 -04:00
return fmt . Errorf ( "expected %d events with reason set to %s and message set to %s\nbut %d actual events occurred. Events : %v" , num , reason , message , count , events . Items )
2016-06-01 15:57:32 -04:00
}
return nil
}
2019-02-07 18:41:16 -05:00
// verifyTotalEvents verifies there are num events in total.
2022-12-12 04:11:10 -05:00
func verifyTotalEvents ( ctx context . Context , e coreclientset . EventInterface , options metav1 . ListOptions , num int ) error {
events , err := e . List ( ctx , options )
2016-06-01 15:57:32 -04:00
if err != nil {
return err
}
2019-02-07 18:41:16 -05:00
count := 0
for _ , event := range events . Items {
count += int ( event . Count )
}
if count != num {
2020-07-08 08:10:50 -04:00
return fmt . Errorf ( "expected total number of events was %d, actual events counted was %d\nEvents : %v" , num , count , events . Items )
2016-06-01 15:57:32 -04:00
}
return nil
}
2017-02-18 01:54:52 -05:00
// verifyNodeCondition verifies specific node condition is generated, if reason and message are empty, they will not be checked
2022-12-12 04:11:10 -05:00
func verifyNodeCondition ( ctx context . Context , n coreclientset . NodeInterface , condition v1 . NodeConditionType , status v1 . ConditionStatus , reason , message string ) error {
node , err := n . Get ( ctx , framework . TestContext . NodeName , metav1 . GetOptions { } )
2016-06-01 15:57:32 -04:00
if err != nil {
return err
}
2019-02-26 14:05:32 -05:00
_ , c := testutils . GetNodeCondition ( & node . Status , condition )
2016-06-01 15:57:32 -04:00
if c == nil {
return fmt . Errorf ( "node condition %q not found" , condition )
}
if c . Status != status || c . Reason != reason || c . Message != message {
return fmt . Errorf ( "unexpected node condition %q: %+v" , condition , c )
}
return nil
}