k8s.io/kubernetes@v1.29.3/test/e2e/framework/providers/gce/util.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package gce 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 "time" 24 25 v1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/util/wait" 28 clientset "k8s.io/client-go/kubernetes" 29 "k8s.io/kubernetes/test/e2e/framework" 30 ) 31 32 // RecreateNodes recreates the given nodes in a managed instance group. 33 func RecreateNodes(c clientset.Interface, nodes []v1.Node) error { 34 // Build mapping from zone to nodes in that zone. 35 nodeNamesByZone := make(map[string][]string) 36 for i := range nodes { 37 node := &nodes[i] 38 39 if zone, ok := node.Labels[v1.LabelFailureDomainBetaZone]; ok { 40 nodeNamesByZone[zone] = append(nodeNamesByZone[zone], node.Name) 41 continue 42 } 43 44 if zone, ok := node.Labels[v1.LabelTopologyZone]; ok { 45 nodeNamesByZone[zone] = append(nodeNamesByZone[zone], node.Name) 46 continue 47 } 48 49 defaultZone := framework.TestContext.CloudConfig.Zone 50 nodeNamesByZone[defaultZone] = append(nodeNamesByZone[defaultZone], node.Name) 51 } 52 53 // Find the sole managed instance group name 54 var instanceGroup string 55 if strings.Contains(framework.TestContext.CloudConfig.NodeInstanceGroup, ",") { 56 return fmt.Errorf("Test does not support cluster setup with more than one managed instance group: %s", framework.TestContext.CloudConfig.NodeInstanceGroup) 57 } 58 instanceGroup = framework.TestContext.CloudConfig.NodeInstanceGroup 59 60 // Recreate the nodes. 61 for zone, nodeNames := range nodeNamesByZone { 62 args := []string{ 63 "compute", 64 fmt.Sprintf("--project=%s", framework.TestContext.CloudConfig.ProjectID), 65 "instance-groups", 66 "managed", 67 "recreate-instances", 68 instanceGroup, 69 } 70 71 args = append(args, fmt.Sprintf("--instances=%s", strings.Join(nodeNames, ","))) 72 args = append(args, fmt.Sprintf("--zone=%s", zone)) 73 framework.Logf("Recreating instance group %s.", instanceGroup) 74 stdout, stderr, err := framework.RunCmd("gcloud", args...) 75 if err != nil { 76 return fmt.Errorf("error recreating nodes: %s\nstdout: %s\nstderr: %s", err, stdout, stderr) 77 } 78 } 79 return nil 80 } 81 82 // WaitForNodeBootIdsToChange waits for the boot ids of the given nodes to change in order to verify the node has been recreated. 83 func WaitForNodeBootIdsToChange(ctx context.Context, c clientset.Interface, nodes []v1.Node, timeout time.Duration) error { 84 errMsg := []string{} 85 for i := range nodes { 86 node := &nodes[i] 87 if err := wait.PollWithContext(ctx, 30*time.Second, timeout, func(ctx context.Context) (bool, error) { 88 newNode, err := c.CoreV1().Nodes().Get(ctx, node.Name, metav1.GetOptions{}) 89 if err != nil { 90 framework.Logf("Could not get node info: %s. Retrying in %v.", err, 30*time.Second) 91 return false, nil 92 } 93 return node.Status.NodeInfo.BootID != newNode.Status.NodeInfo.BootID, nil 94 }); err != nil { 95 errMsg = append(errMsg, "Error waiting for node %s boot ID to change: %s", node.Name, err.Error()) 96 } 97 } 98 if len(errMsg) > 0 { 99 return fmt.Errorf(strings.Join(errMsg, ",")) 100 } 101 return nil 102 }