1
16
17 package node
18
19 import (
20 "context"
21 "fmt"
22 "time"
23
24 "github.com/onsi/ginkgo/v2"
25 "github.com/onsi/gomega"
26
27 v1 "k8s.io/api/core/v1"
28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29 "k8s.io/apimachinery/pkg/util/wait"
30 clientset "k8s.io/client-go/kubernetes"
31 testutils "k8s.io/kubernetes/test/utils"
32
33 "k8s.io/kubernetes/test/e2e/framework"
34 )
35
36 const (
37
38 largeClusterThreshold = 100
39 )
40
41
42
43 func WaitForAllNodesSchedulable(ctx context.Context, c clientset.Interface, timeout time.Duration) error {
44 if framework.TestContext.AllowedNotReadyNodes == -1 {
45 return nil
46 }
47
48 framework.Logf("Waiting up to %v for all (but %d) nodes to be schedulable", timeout, framework.TestContext.AllowedNotReadyNodes)
49 return wait.PollImmediateWithContext(
50 ctx,
51 30*time.Second,
52 timeout,
53 CheckReadyForTests(ctx, c, framework.TestContext.NonblockingTaints, framework.TestContext.AllowedNotReadyNodes, largeClusterThreshold),
54 )
55 }
56
57
58 func AddOrUpdateLabelOnNode(c clientset.Interface, nodeName string, labelKey, labelValue string) {
59 framework.ExpectNoError(testutils.AddLabelsToNode(c, nodeName, map[string]string{labelKey: labelValue}))
60 }
61
62
63 func ExpectNodeHasLabel(ctx context.Context, c clientset.Interface, nodeName string, labelKey string, labelValue string) {
64 ginkgo.By("verifying the node has the label " + labelKey + " " + labelValue)
65 node, err := c.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{})
66 framework.ExpectNoError(err)
67 gomega.Expect(node.Labels).To(gomega.HaveKeyWithValue(labelKey, labelValue))
68 }
69
70
71
72 func RemoveLabelOffNode(c clientset.Interface, nodeName string, labelKey string) {
73 ginkgo.By("removing the label " + labelKey + " off the node " + nodeName)
74 framework.ExpectNoError(testutils.RemoveLabelOffNode(c, nodeName, []string{labelKey}))
75
76 ginkgo.By("verifying the node doesn't have the label " + labelKey)
77 framework.ExpectNoError(testutils.VerifyLabelsRemoved(c, nodeName, []string{labelKey}))
78 }
79
80
81 func ExpectNodeHasTaint(ctx context.Context, c clientset.Interface, nodeName string, taint *v1.Taint) {
82 ginkgo.By("verifying the node has the taint " + taint.ToString())
83 if has, err := NodeHasTaint(ctx, c, nodeName, taint); !has {
84 framework.ExpectNoError(err)
85 framework.Failf("Failed to find taint %s on node %s", taint.ToString(), nodeName)
86 }
87 }
88
89
90 func NodeHasTaint(ctx context.Context, c clientset.Interface, nodeName string, taint *v1.Taint) (bool, error) {
91 node, err := c.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{})
92 if err != nil {
93 return false, err
94 }
95
96 nodeTaints := node.Spec.Taints
97
98 if len(nodeTaints) == 0 || !taintExists(nodeTaints, taint) {
99 return false, nil
100 }
101 return true, nil
102 }
103
104
105
106
107
108
109 func AllNodesReady(ctx context.Context, c clientset.Interface, timeout time.Duration) error {
110 if err := allNodesReady(ctx, c, timeout); err != nil {
111 return fmt.Errorf("checking for ready nodes: %w", err)
112 }
113 return nil
114 }
115
116 func allNodesReady(ctx context.Context, c clientset.Interface, timeout time.Duration) error {
117 if framework.TestContext.AllowedNotReadyNodes == -1 {
118 return nil
119 }
120
121 framework.Logf("Waiting up to %v for all (but %d) nodes to be ready", timeout, framework.TestContext.AllowedNotReadyNodes)
122
123 var notReady []*v1.Node
124 err := wait.PollUntilContextTimeout(ctx, framework.Poll, timeout, true, func(ctx context.Context) (bool, error) {
125 notReady = nil
126
127 nodes, err := c.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
128 if err != nil {
129 return false, err
130 }
131 for i := range nodes.Items {
132 node := &nodes.Items[i]
133 if !IsConditionSetAsExpected(node, v1.NodeReady, true) {
134 notReady = append(notReady, node)
135 }
136 }
137
138
139
140
141
142 return len(notReady) <= framework.TestContext.AllowedNotReadyNodes, nil
143 })
144
145 if err != nil && !wait.Interrupted(err) {
146 return err
147 }
148
149 if len(notReady) > framework.TestContext.AllowedNotReadyNodes {
150 msg := ""
151 for _, node := range notReady {
152 msg = fmt.Sprintf("%s, %s", msg, node.Name)
153 }
154 return fmt.Errorf("Not ready nodes: %#v", msg)
155 }
156 return nil
157 }
158
159
160 func taintExists(taints []v1.Taint, taintToFind *v1.Taint) bool {
161 for _, taint := range taints {
162 if taint.MatchTaint(taintToFind) {
163 return true
164 }
165 }
166 return false
167 }
168
View as plain text