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  }