@@ -17,6 +17,7 @@ limitations under the License.
1717package actions
1818
1919import (
20+ "context"
2021 "fmt"
2122 "math/rand"
2223 "regexp"
@@ -30,9 +31,9 @@ import (
3031)
3132
3233// waitNewControlPlaneNodeReady waits for a new control plane node reaching the target state after init/join
33- func waitNewControlPlaneNodeReady (c * status.Cluster , n * status.Node , wait time.Duration ) error {
34+ func waitNewControlPlaneNodeReady (ctx context. Context , c * status.Cluster , n * status.Node , wait time.Duration ) error {
3435 n .Infof ("waiting for Node and control-plane Pods to become Ready (timeout %s)" , wait )
35- if pass := waitFor (c , n , wait ,
36+ if pass := waitFor (ctx , c , n , wait ,
3637 nodeIsReady ,
3738 staticPodIsReady ("kube-apiserver" ),
3839 staticPodIsReady ("kube-controller-manager" ),
@@ -44,8 +45,8 @@ func waitNewControlPlaneNodeReady(c *status.Cluster, n *status.Node, wait time.D
4445 return nil
4546}
4647
47- func waitForPodsRunning (c * status.Cluster , n * status.Node , wait time.Duration , label string , replicas int ) error {
48- if pass := waitFor (c , n , wait ,
48+ func waitForPodsRunning (ctx context. Context , c * status.Cluster , n * status.Node , wait time.Duration , label string , replicas int ) error {
49+ if pass := waitFor (ctx , c , n , wait ,
4950 podsAreRunning (n , label , replicas ),
5051 ); ! pass {
5152 return errors .New ("timeout: Node and control-plane did not reach target state" )
@@ -55,9 +56,9 @@ func waitForPodsRunning(c *status.Cluster, n *status.Node, wait time.Duration, l
5556}
5657
5758// waitForNodePort waits for a nodePort to become ready
58- func waitForNodePort (c * status.Cluster , n * status.Node , wait time.Duration , nodePort string ) error {
59+ func waitForNodePort (ctx context. Context , c * status.Cluster , n * status.Node , wait time.Duration , nodePort string ) error {
5960 n .Infof ("waiting for NodePort %q to become ready (timeout %s)" , nodePort , wait )
60- if pass := waitFor (c , n , wait ,
61+ if pass := waitFor (ctx , c , n , wait ,
6162 nodePortIsReady (n , nodePort ),
6263 ); ! pass {
6364 return errors .New ("timeout: NodePort not ready" )
@@ -67,9 +68,9 @@ func waitForNodePort(c *status.Cluster, n *status.Node, wait time.Duration, node
6768}
6869
6970// waitNewWorkerNodeReady waits for a new control plane node reaching the target state after join
70- func waitNewWorkerNodeReady (c * status.Cluster , n * status.Node , wait time.Duration ) error {
71+ func waitNewWorkerNodeReady (ctx context. Context , c * status.Cluster , n * status.Node , wait time.Duration ) error {
7172 n .Infof ("waiting for Node to become Ready (timeout %s)" , wait )
72- if pass := waitFor (c , n , wait ,
73+ if pass := waitFor (ctx , c , n , wait ,
7374 nodeIsReady ,
7475 ); ! pass {
7576 return errors .New ("timeout: Node did not reach target state" )
@@ -79,11 +80,11 @@ func waitNewWorkerNodeReady(c *status.Cluster, n *status.Node, wait time.Duratio
7980}
8081
8182// waitControlPlaneUpgraded waits for a control plane node reaching the target state after upgrade
82- func waitControlPlaneUpgraded (c * status.Cluster , n * status.Node , upgradeVersion * K8sVersion.Version , wait time.Duration ) error {
83+ func waitControlPlaneUpgraded (ctx context. Context , c * status.Cluster , n * status.Node , upgradeVersion * K8sVersion.Version , wait time.Duration ) error {
8384 version := kubernetesVersionToImageTag (upgradeVersion .String ())
8485
8586 n .Infof ("waiting for control-plane Pods to restart with the new version (timeout %s)" , wait )
86- if pass := waitFor (c , n , wait ,
87+ if pass := waitFor (ctx , c , n , wait ,
8788 staticPodHasVersion ("kube-apiserver" , version ),
8889 staticPodHasVersion ("kube-controller-manager" , version ),
8990 staticPodHasVersion ("kube-scheduler" , version ),
@@ -95,11 +96,11 @@ func waitControlPlaneUpgraded(c *status.Cluster, n *status.Node, upgradeVersion
9596}
9697
9798// waitKubeletUpgraded waits for a node reaching the target state after upgrade
98- func waitKubeletUpgraded (c * status.Cluster , n * status.Node , upgradeVersion * K8sVersion.Version , wait time.Duration ) error {
99+ func waitKubeletUpgraded (ctx context. Context , c * status.Cluster , n * status.Node , upgradeVersion * K8sVersion.Version , wait time.Duration ) error {
99100 version := upgradeVersion .String ()
100101
101102 n .Infof ("waiting for node to restart with the new version (timeout %s)" , wait )
102- if pass := waitFor (c , n , wait ,
103+ if pass := waitFor (ctx , c , n , wait ,
103104 nodeHasKubernetesVersion (version ),
104105 ); ! pass {
105106 return errors .New ("timeout: node did not reach target state" )
@@ -111,9 +112,9 @@ func waitKubeletUpgraded(c *status.Cluster, n *status.Node, upgradeVersion *K8sV
111112// waitKubeletHasRBAC waits for the kubelet to have access to the expected config map
112113// please note that this is a temporary workaround for a problem we are observing on upgrades while
113114// executing node upgrades immediately after control-plane upgrade.
114- func waitKubeletHasRBAC (c * status.Cluster , n * status.Node , upgradeVersion * K8sVersion.Version , wait time.Duration ) error {
115+ func waitKubeletHasRBAC (ctx context. Context , c * status.Cluster , n * status.Node , upgradeVersion * K8sVersion.Version , wait time.Duration ) error {
115116 n .Infof ("waiting for kubelet RBAC validation - workaround (timeout %s)" , wait )
116- if pass := waitFor (c , n , wait ,
117+ if pass := waitFor (ctx , c , n , wait ,
117118 kubeletHasRBAC (upgradeVersion .Major (), upgradeVersion .Minor ()),
118119 ); ! pass {
119120 return errors .New ("timeout: Node did not reach target state" )
@@ -127,18 +128,18 @@ type try func(*status.Cluster, *status.Node) bool
127128
128129// waitFor implements the waiter core logic that is responsible for testing all the given contitions
129130// until are satisfied or a timeout are reached
130- func waitFor (c * status.Cluster , n * status.Node , timeout time.Duration , conditions ... try ) bool {
131+ func waitFor (ctx context. Context , c * status.Cluster , n * status.Node , timeout time.Duration , conditions ... try ) bool {
131132 // if timeout is 0 or no conditions are defined, exit fast
132133 if timeout == time .Duration (0 ) {
133134 fmt .Println ("Timeout set 0, skipping wait" )
134135 return true
135136 }
136137
137- // sets the timeout timer
138- timer := time . NewTimer ( timeout )
138+ ctx , cancel := context . WithTimeout ( ctx , timeout )
139+ defer cancel ( )
139140
140141 // runs all the conditions in parallel
141- pass := make (chan bool )
142+ pass := make (chan struct {}, len ( conditions ) )
142143 for _ , wc := range conditions {
143144 // clone the condition func to make the closure point to right value
144145 // even after the for loop moves to the next condition
@@ -147,15 +148,33 @@ func waitFor(c *status.Cluster, n *status.Node, timeout time.Duration, condition
147148 // run the condition in a go routine until it pass
148149 go func () {
149150 // creates an arbitrary skew before starting a wait loop
150- time .Sleep (time .Duration (rand .Intn (500 )) * time .Millisecond )
151+ timer := time .NewTimer (time .Duration (rand .Intn (500 )) * time .Millisecond )
152+ defer timer .Stop ()
153+
154+ select {
155+ case <- ctx .Done ():
156+ return
157+ case <- timer .C :
158+ }
151159
152160 for {
161+ select {
162+ case <- ctx .Done ():
163+ return
164+ default :
165+ }
166+
153167 if x (c , n ) {
154- <- pass
168+ pass <- struct {}{}
155169 break
156170 }
157171 // add a little delay + jitter before retry
158- time .Sleep (1 * time .Second + time .Duration (rand .Intn (500 ))* time .Millisecond )
172+ timer .Reset (1 * time .Second + time .Duration (rand .Intn (500 ))* time .Millisecond )
173+ select {
174+ case <- ctx .Done ():
175+ return
176+ case <- timer .C :
177+ }
159178 }
160179 }()
161180 }
@@ -164,14 +183,12 @@ func waitFor(c *status.Cluster, n *status.Node, timeout time.Duration, condition
164183 passed := 0
165184 for {
166185 select {
167- case pass <- true :
186+ case <- pass :
168187 passed ++
169188 if passed == len (conditions ) {
170189 return true
171190 }
172- case <- timer .C :
173- // close the channel if timeout occurs, this will release all the blocked receives
174- close (pass )
191+ case <- ctx .Done ():
175192 return false
176193 }
177194 }
0 commit comments