2016-06-01 19:57:32 +00:00
|
|
|
/*
|
2016-06-03 00:25:58 +00:00
|
|
|
Copyright 2016 The Kubernetes Authors.
|
2016-06-01 19:57:32 +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"
|
2016-11-03 04:21:11 +00:00
|
|
|
"path/filepath"
|
2016-06-01 19:57:32 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"k8s.io/kubernetes/pkg/api"
|
2016-11-18 20:55:17 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api/v1"
|
2016-12-07 14:40:26 +00:00
|
|
|
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
|
2016-12-15 17:52:14 +00:00
|
|
|
rbacv1alpha1 "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1"
|
2016-12-14 01:18:17 +00:00
|
|
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
|
|
|
coreclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/core/v1"
|
2016-06-01 19:57:32 +00:00
|
|
|
"k8s.io/kubernetes/pkg/fields"
|
|
|
|
"k8s.io/kubernetes/pkg/labels"
|
2016-12-15 17:52:14 +00:00
|
|
|
"k8s.io/kubernetes/pkg/runtime/schema"
|
|
|
|
"k8s.io/kubernetes/pkg/serviceaccount"
|
2016-06-01 19:57:32 +00:00
|
|
|
"k8s.io/kubernetes/pkg/util/system"
|
2016-07-26 15:13:18 +00:00
|
|
|
"k8s.io/kubernetes/pkg/util/uuid"
|
2016-06-01 19:57:32 +00:00
|
|
|
"k8s.io/kubernetes/test/e2e/framework"
|
|
|
|
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ = framework.KubeDescribe("NodeProblemDetector", func() {
|
|
|
|
const (
|
|
|
|
pollInterval = 1 * time.Second
|
|
|
|
pollConsistent = 5 * time.Second
|
|
|
|
pollTimeout = 1 * time.Minute
|
2016-11-03 04:21:11 +00:00
|
|
|
image = "gcr.io/google_containers/node-problem-detector:v0.2"
|
2016-06-01 19:57:32 +00:00
|
|
|
)
|
|
|
|
f := framework.NewDefaultFramework("node-problem-detector")
|
2016-10-18 13:00:38 +00:00
|
|
|
var c clientset.Interface
|
2016-06-01 19:57:32 +00:00
|
|
|
var uid string
|
|
|
|
var ns, name, configName, eventNamespace string
|
2016-11-03 04:21:11 +00:00
|
|
|
var nodeTime time.Time
|
2016-06-01 19:57:32 +00:00
|
|
|
BeforeEach(func() {
|
2016-10-18 13:00:38 +00:00
|
|
|
c = f.ClientSet
|
2016-06-01 19:57:32 +00:00
|
|
|
ns = f.Namespace.Name
|
2016-07-26 15:13:18 +00:00
|
|
|
uid = string(uuid.NewUUID())
|
2016-06-01 19:57:32 +00: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.
|
2016-11-18 20:55:17 +00:00
|
|
|
eventNamespace = v1.NamespaceDefault
|
2016-12-15 17:52:14 +00:00
|
|
|
|
|
|
|
// this test wants extra permissions. Since the namespace names are unique, we can leave this
|
|
|
|
// lying around so we don't have to race any caches
|
2017-01-03 12:52:55 +00:00
|
|
|
framework.BindClusterRole(f.ClientSet.Rbac(), "cluster-admin", f.Namespace.Name,
|
|
|
|
rbacv1alpha1.Subject{Kind: rbacv1alpha1.ServiceAccountKind, Namespace: f.Namespace.Name, Name: "default"})
|
2016-12-15 17:52:14 +00:00
|
|
|
|
2017-01-03 12:52:55 +00:00
|
|
|
err := framework.WaitForAuthorizationUpdate(f.ClientSet.Authorization(),
|
2016-12-15 17:52:14 +00:00
|
|
|
serviceaccount.MakeUsername(f.Namespace.Name, "default"),
|
|
|
|
"", "create", schema.GroupResource{Resource: "pods"}, true)
|
|
|
|
framework.ExpectNoError(err)
|
2016-06-01 19:57:32 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// Test kernel monitor. We may add other tests if we have more problem daemons in the future.
|
|
|
|
framework.KubeDescribe("KernelMonitor", func() {
|
|
|
|
const (
|
|
|
|
// Use test condition to avoid conflict with real node problem detector
|
|
|
|
// TODO(random-liu): Now node condition could be arbitrary string, consider wether we need to
|
|
|
|
// add TestCondition when switching to predefined condition list.
|
2016-11-18 20:55:17 +00:00
|
|
|
condition = v1.NodeConditionType("TestCondition")
|
2016-11-03 04:21:11 +00:00
|
|
|
lookback = time.Hour // Assume the test won't take more than 1 hour, in fact it usually only takes 90 seconds.
|
|
|
|
startPattern = "test reboot"
|
|
|
|
|
|
|
|
// File paths used in the test.
|
|
|
|
logDir = "/log"
|
|
|
|
logFile = "test.log"
|
|
|
|
configDir = "/config"
|
|
|
|
configFile = "testconfig.json"
|
|
|
|
etcLocaltime = "/etc/localtime"
|
|
|
|
|
|
|
|
// Volumes used in the test.
|
|
|
|
configVolume = "config"
|
|
|
|
logVolume = "log"
|
|
|
|
localtimeVolume = "localtime"
|
|
|
|
|
|
|
|
// Reasons and messages used in the test.
|
2016-06-01 19:57:32 +00:00
|
|
|
defaultReason = "Default"
|
|
|
|
defaultMessage = "default message"
|
|
|
|
tempReason = "Temporary"
|
|
|
|
tempMessage = "temporary error"
|
|
|
|
permReason = "Permanent"
|
|
|
|
permMessage = "permanent error"
|
|
|
|
)
|
|
|
|
var source, config, tmpDir string
|
2016-11-18 20:55:17 +00:00
|
|
|
var node *v1.Node
|
|
|
|
var eventListOptions v1.ListOptions
|
2016-11-03 04:21:11 +00:00
|
|
|
injectCommand := func(timestamp time.Time, log string, num int) string {
|
2016-06-01 19:57:32 +00:00
|
|
|
var commands []string
|
|
|
|
for i := 0; i < num; i++ {
|
2016-11-03 04:21:11 +00:00
|
|
|
commands = append(commands, fmt.Sprintf("echo \"%s kernel: [0.000000] %s\" >> %s/%s",
|
|
|
|
timestamp.Format(time.Stamp), log, tmpDir, logFile))
|
2016-06-01 19:57:32 +00:00
|
|
|
}
|
|
|
|
return strings.Join(commands, ";")
|
|
|
|
}
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
2016-06-24 14:36:07 +00:00
|
|
|
framework.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
|
2016-06-01 19:57:32 +00:00
|
|
|
// Randomize the source name to avoid conflict with real node problem detector
|
|
|
|
source = "kernel-monitor-" + uid
|
|
|
|
config = `
|
|
|
|
{
|
2016-11-03 04:21:11 +00:00
|
|
|
"logPath": "` + filepath.Join(logDir, logFile) + `",
|
|
|
|
"lookback": "` + lookback.String() + `",
|
|
|
|
"startPattern": "` + startPattern + `",
|
2016-06-01 19:57:32 +00: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) + `",
|
|
|
|
"reason": "` + permReason + `",
|
|
|
|
"pattern": "` + permMessage + `"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}`
|
|
|
|
By("Get a non master node to run the pod")
|
2016-11-18 20:55:17 +00:00
|
|
|
nodes, err := c.Core().Nodes().List(v1.ListOptions{})
|
2016-06-01 19:57:32 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
node = nil
|
|
|
|
for _, n := range nodes.Items {
|
2016-11-18 20:55:17 +00:00
|
|
|
if !system.IsMasterNode(n.Name) {
|
2016-06-01 19:57:32 +00:00
|
|
|
node = &n
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Expect(node).NotTo(BeNil())
|
|
|
|
By("Generate event list options")
|
|
|
|
selector := fields.Set{
|
|
|
|
"involvedObject.kind": "Node",
|
|
|
|
"involvedObject.name": node.Name,
|
2016-11-18 20:55:17 +00:00
|
|
|
"involvedObject.namespace": v1.NamespaceAll,
|
2016-06-01 19:57:32 +00:00
|
|
|
"source": source,
|
2016-11-18 20:55:17 +00:00
|
|
|
}.AsSelector().String()
|
|
|
|
eventListOptions = v1.ListOptions{FieldSelector: selector}
|
2016-06-01 19:57:32 +00:00
|
|
|
By("Create the test log file")
|
|
|
|
tmpDir = "/tmp/" + name
|
|
|
|
cmd := fmt.Sprintf("mkdir %s; > %s/%s", tmpDir, tmpDir, logFile)
|
|
|
|
Expect(framework.IssueSSHCommand(cmd, framework.TestContext.Provider, node)).To(Succeed())
|
|
|
|
By("Create config map for the node problem detector")
|
2016-11-18 20:55:17 +00:00
|
|
|
_, err = c.Core().ConfigMaps(ns).Create(&v1.ConfigMap{
|
|
|
|
ObjectMeta: v1.ObjectMeta{
|
2016-06-01 19:57:32 +00:00
|
|
|
Name: configName,
|
|
|
|
},
|
|
|
|
Data: map[string]string{configFile: config},
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("Create the node problem detector")
|
2016-11-18 20:55:17 +00:00
|
|
|
_, err = c.Core().Pods(ns).Create(&v1.Pod{
|
|
|
|
ObjectMeta: v1.ObjectMeta{
|
2016-06-01 19:57:32 +00:00
|
|
|
Name: name,
|
|
|
|
},
|
2016-11-18 20:55:17 +00:00
|
|
|
Spec: v1.PodSpec{
|
2016-06-01 19:57:32 +00:00
|
|
|
NodeName: node.Name,
|
2016-11-18 20:55:17 +00:00
|
|
|
HostNetwork: true,
|
|
|
|
SecurityContext: &v1.PodSecurityContext{},
|
|
|
|
Volumes: []v1.Volume{
|
2016-06-01 19:57:32 +00:00
|
|
|
{
|
|
|
|
Name: configVolume,
|
2016-11-18 20:55:17 +00:00
|
|
|
VolumeSource: v1.VolumeSource{
|
|
|
|
ConfigMap: &v1.ConfigMapVolumeSource{
|
|
|
|
LocalObjectReference: v1.LocalObjectReference{Name: configName},
|
2016-06-01 19:57:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: logVolume,
|
2016-11-18 20:55:17 +00:00
|
|
|
VolumeSource: v1.VolumeSource{
|
|
|
|
HostPath: &v1.HostPathVolumeSource{Path: tmpDir},
|
2016-06-01 19:57:32 +00:00
|
|
|
},
|
|
|
|
},
|
2016-11-03 04:21:11 +00:00
|
|
|
{
|
|
|
|
Name: localtimeVolume,
|
2016-11-18 20:55:17 +00:00
|
|
|
VolumeSource: v1.VolumeSource{
|
|
|
|
HostPath: &v1.HostPathVolumeSource{Path: etcLocaltime},
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
},
|
2016-06-01 19:57:32 +00:00
|
|
|
},
|
2016-11-18 20:55:17 +00:00
|
|
|
Containers: []v1.Container{
|
2016-06-01 19:57:32 +00:00
|
|
|
{
|
2016-11-03 04:21:11 +00:00
|
|
|
Name: name,
|
|
|
|
Image: image,
|
|
|
|
Command: []string{"/node-problem-detector", "--kernel-monitor=" + filepath.Join(configDir, configFile)},
|
2016-11-18 20:55:17 +00:00
|
|
|
ImagePullPolicy: v1.PullAlways,
|
|
|
|
Env: []v1.EnvVar{
|
2016-11-03 04:21:11 +00:00
|
|
|
{
|
|
|
|
Name: "NODE_NAME",
|
2016-11-18 20:55:17 +00:00
|
|
|
ValueFrom: &v1.EnvVarSource{
|
|
|
|
FieldRef: &v1.ObjectFieldSelector{
|
2016-11-03 04:21:11 +00:00
|
|
|
APIVersion: "v1",
|
|
|
|
FieldPath: "spec.nodeName",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-11-18 20:55:17 +00:00
|
|
|
VolumeMounts: []v1.VolumeMount{
|
2016-06-01 19:57:32 +00:00
|
|
|
{
|
|
|
|
Name: logVolume,
|
|
|
|
MountPath: logDir,
|
|
|
|
},
|
2016-11-03 04:21:11 +00:00
|
|
|
{
|
|
|
|
Name: localtimeVolume,
|
|
|
|
MountPath: etcLocaltime,
|
|
|
|
},
|
2016-06-01 19:57:32 +00:00
|
|
|
{
|
|
|
|
Name: configVolume,
|
|
|
|
MountPath: configDir,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("Wait for node problem detector running")
|
|
|
|
Expect(f.WaitForPodRunning(name)).To(Succeed())
|
2016-11-03 04:21:11 +00:00
|
|
|
// Get the node time
|
|
|
|
nodeIP := framework.GetNodeExternalIP(node)
|
|
|
|
result, err := framework.SSH("date '+%FT%T.%N%:z'", nodeIP, framework.TestContext.Provider)
|
|
|
|
Expect(err).ShouldNot(HaveOccurred())
|
|
|
|
Expect(result.Code).Should(BeZero())
|
|
|
|
nodeTime, err = time.Parse(time.RFC3339, strings.TrimSpace(result.Stdout))
|
|
|
|
Expect(err).ShouldNot(HaveOccurred())
|
2016-06-01 19:57:32 +00:00
|
|
|
})
|
|
|
|
|
2016-06-13 17:55:36 +00:00
|
|
|
It("should generate node condition and events for corresponding errors", func() {
|
2016-11-03 04:21:11 +00:00
|
|
|
for _, test := range []struct {
|
|
|
|
description string
|
|
|
|
timestamp time.Time
|
|
|
|
message string
|
|
|
|
messageNum int
|
|
|
|
events int
|
|
|
|
conditionReason string
|
|
|
|
conditionMessage string
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType v1.ConditionStatus
|
2016-11-03 04:21:11 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
description: "should generate default node condition",
|
|
|
|
conditionReason: defaultReason,
|
|
|
|
conditionMessage: defaultMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionFalse,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should not generate events for too old log",
|
|
|
|
timestamp: nodeTime.Add(-3 * lookback), // Assume 3*lookback is old enough
|
|
|
|
message: tempMessage,
|
|
|
|
messageNum: 3,
|
|
|
|
conditionReason: defaultReason,
|
|
|
|
conditionMessage: defaultMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionFalse,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should not change node condition for too old log",
|
|
|
|
timestamp: nodeTime.Add(-3 * lookback), // Assume 3*lookback is old enough
|
|
|
|
message: permMessage,
|
|
|
|
messageNum: 1,
|
|
|
|
conditionReason: defaultReason,
|
|
|
|
conditionMessage: defaultMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionFalse,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should generate event for old log within lookback duration",
|
|
|
|
timestamp: nodeTime.Add(-1 * time.Minute),
|
|
|
|
message: tempMessage,
|
|
|
|
messageNum: 3,
|
|
|
|
events: 3,
|
|
|
|
conditionReason: defaultReason,
|
|
|
|
conditionMessage: defaultMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionFalse,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should change node condition for old log within lookback duration",
|
|
|
|
timestamp: nodeTime.Add(-1 * time.Minute),
|
|
|
|
message: permMessage,
|
|
|
|
messageNum: 1,
|
|
|
|
events: 3, // event number should not change
|
|
|
|
conditionReason: permReason,
|
|
|
|
conditionMessage: permMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionTrue,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should reset node condition if the node is reboot",
|
|
|
|
timestamp: nodeTime,
|
|
|
|
message: startPattern,
|
|
|
|
messageNum: 1,
|
|
|
|
events: 3, // event number should not change
|
|
|
|
conditionReason: defaultReason,
|
|
|
|
conditionMessage: defaultMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionFalse,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should generate event for new log",
|
|
|
|
timestamp: nodeTime.Add(5 * time.Minute),
|
|
|
|
message: tempMessage,
|
|
|
|
messageNum: 3,
|
|
|
|
events: 6,
|
|
|
|
conditionReason: defaultReason,
|
|
|
|
conditionMessage: defaultMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionFalse,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: "should change node condition for new log",
|
|
|
|
timestamp: nodeTime.Add(5 * time.Minute),
|
|
|
|
message: permMessage,
|
|
|
|
messageNum: 1,
|
|
|
|
events: 6, // event number should not change
|
|
|
|
conditionReason: permReason,
|
|
|
|
conditionMessage: permMessage,
|
2016-11-18 20:55:17 +00:00
|
|
|
conditionType: v1.ConditionTrue,
|
2016-11-03 04:21:11 +00:00
|
|
|
},
|
|
|
|
} {
|
|
|
|
By(test.description)
|
|
|
|
if test.messageNum > 0 {
|
|
|
|
By(fmt.Sprintf("Inject %d logs: %q", test.messageNum, test.message))
|
|
|
|
cmd := injectCommand(test.timestamp, test.message, test.messageNum)
|
|
|
|
Expect(framework.IssueSSHCommand(cmd, framework.TestContext.Provider, node)).To(Succeed())
|
|
|
|
}
|
|
|
|
|
|
|
|
By(fmt.Sprintf("Wait for %d events generated", test.events))
|
|
|
|
Eventually(func() error {
|
|
|
|
return verifyEvents(c.Core().Events(eventNamespace), eventListOptions, test.events, tempReason, tempMessage)
|
|
|
|
}, pollTimeout, pollInterval).Should(Succeed())
|
|
|
|
By(fmt.Sprintf("Make sure only %d events generated", test.events))
|
|
|
|
Consistently(func() error {
|
|
|
|
return verifyEvents(c.Core().Events(eventNamespace), eventListOptions, test.events, tempReason, tempMessage)
|
|
|
|
}, pollConsistent, pollInterval).Should(Succeed())
|
|
|
|
|
|
|
|
By(fmt.Sprintf("Make sure node condition %q is set", condition))
|
|
|
|
Eventually(func() error {
|
|
|
|
return verifyCondition(c.Core().Nodes(), node.Name, condition, test.conditionType, test.conditionReason, test.conditionMessage)
|
|
|
|
}, pollTimeout, pollInterval).Should(Succeed())
|
|
|
|
By(fmt.Sprintf("Make sure node condition %q is stable", condition))
|
|
|
|
Consistently(func() error {
|
|
|
|
return verifyCondition(c.Core().Nodes(), node.Name, condition, test.conditionType, test.conditionReason, test.conditionMessage)
|
|
|
|
}, pollConsistent, pollInterval).Should(Succeed())
|
|
|
|
}
|
2016-06-01 19:57:32 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
AfterEach(func() {
|
2016-11-03 04:21:11 +00:00
|
|
|
if CurrentGinkgoTestDescription().Failed && framework.TestContext.DumpLogsOnFailure {
|
|
|
|
By("Get node problem detector log")
|
|
|
|
log, err := framework.GetPodLogs(c, ns, name, name)
|
|
|
|
Expect(err).ShouldNot(HaveOccurred())
|
|
|
|
framework.Logf("Node Problem Detector logs:\n %s", log)
|
|
|
|
}
|
2016-06-01 19:57:32 +00:00
|
|
|
By("Delete the node problem detector")
|
2016-11-18 20:55:17 +00:00
|
|
|
c.Core().Pods(ns).Delete(name, v1.NewDeleteOptions(0))
|
2016-06-01 19:57:32 +00:00
|
|
|
By("Wait for the node problem detector to disappear")
|
|
|
|
Expect(framework.WaitForPodToDisappear(c, ns, name, labels.Everything(), pollInterval, pollTimeout)).To(Succeed())
|
|
|
|
By("Delete the config map")
|
2016-10-18 13:00:38 +00:00
|
|
|
c.Core().ConfigMaps(ns).Delete(configName, nil)
|
2016-06-01 19:57:32 +00:00
|
|
|
By("Clean up the events")
|
2016-11-18 20:55:17 +00:00
|
|
|
Expect(c.Core().Events(eventNamespace).DeleteCollection(v1.NewDeleteOptions(0), eventListOptions)).To(Succeed())
|
2016-06-01 19:57:32 +00:00
|
|
|
By("Clean up the node condition")
|
|
|
|
patch := []byte(fmt.Sprintf(`{"status":{"conditions":[{"$patch":"delete","type":"%s"}]}}`, condition))
|
2016-10-18 13:00:38 +00:00
|
|
|
c.Core().RESTClient().Patch(api.StrategicMergePatchType).Resource("nodes").Name(node.Name).SubResource("status").Body(patch).Do()
|
2016-06-01 19:57:32 +00:00
|
|
|
By("Clean up the temporary directory")
|
|
|
|
framework.IssueSSHCommand(fmt.Sprintf("rm -r %s", tmpDir), framework.TestContext.Provider, node)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
// verifyEvents verifies there are num specific events generated
|
2016-11-18 20:55:17 +00:00
|
|
|
func verifyEvents(e coreclientset.EventInterface, options v1.ListOptions, num int, reason, message string) error {
|
2016-06-01 19:57:32 +00:00
|
|
|
events, err := e.List(options)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
count := 0
|
|
|
|
for _, event := range events.Items {
|
|
|
|
if event.Reason != reason || event.Message != message {
|
|
|
|
return fmt.Errorf("unexpected event: %v", event)
|
|
|
|
}
|
|
|
|
count += int(event.Count)
|
|
|
|
}
|
|
|
|
if count != num {
|
|
|
|
return fmt.Errorf("expect event number %d, got %d: %v", num, count, events.Items)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// verifyNoEvents verifies there is no event generated
|
2016-11-18 20:55:17 +00:00
|
|
|
func verifyNoEvents(e coreclientset.EventInterface, options v1.ListOptions) error {
|
2016-06-01 19:57:32 +00:00
|
|
|
events, err := e.List(options)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(events.Items) != 0 {
|
|
|
|
return fmt.Errorf("unexpected events: %v", events.Items)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// verifyCondition verifies specific node condition is generated, if reason and message are empty, they will not be checked
|
2016-11-18 20:55:17 +00:00
|
|
|
func verifyCondition(n coreclientset.NodeInterface, nodeName string, condition v1.NodeConditionType, status v1.ConditionStatus, reason, message string) error {
|
2016-12-07 14:40:26 +00:00
|
|
|
node, err := n.Get(nodeName, metav1.GetOptions{})
|
2016-06-01 19:57:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-11-18 20:55:17 +00:00
|
|
|
_, c := v1.GetNodeCondition(&node.Status, condition)
|
2016-06-01 19:57:32 +00: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
|
|
|
|
}
|