k8s.io/kubernetes@v1.29.3/test/integration/framework/perf_utils.go (about)

     1  /*
     2  Copyright 2016 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 framework
    18  
    19  import (
    20  	"context"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/api/resource"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/util/rand"
    26  	clientset "k8s.io/client-go/kubernetes"
    27  	"k8s.io/klog/v2"
    28  	testutils "k8s.io/kubernetes/test/utils"
    29  )
    30  
    31  const (
    32  	retries = 5
    33  )
    34  
    35  // IntegrationTestNodePreparer holds configuration information for the test node preparer.
    36  type IntegrationTestNodePreparer struct {
    37  	client          clientset.Interface
    38  	countToStrategy []testutils.CountToStrategy
    39  	nodeNamePrefix  string
    40  	nodeSpec        *v1.Node
    41  }
    42  
    43  // NewIntegrationTestNodePreparer creates an IntegrationTestNodePreparer configured with defaults.
    44  func NewIntegrationTestNodePreparer(client clientset.Interface, countToStrategy []testutils.CountToStrategy, nodeNamePrefix string) testutils.TestNodePreparer {
    45  	return &IntegrationTestNodePreparer{
    46  		client:          client,
    47  		countToStrategy: countToStrategy,
    48  		nodeNamePrefix:  nodeNamePrefix,
    49  	}
    50  }
    51  
    52  // NewIntegrationTestNodePreparerWithNodeSpec creates an IntegrationTestNodePreparer configured with nodespec.
    53  func NewIntegrationTestNodePreparerWithNodeSpec(client clientset.Interface, countToStrategy []testutils.CountToStrategy, nodeSpec *v1.Node) testutils.TestNodePreparer {
    54  	return &IntegrationTestNodePreparer{
    55  		client:          client,
    56  		countToStrategy: countToStrategy,
    57  		nodeSpec:        nodeSpec,
    58  	}
    59  }
    60  
    61  // PrepareNodes prepares countToStrategy test nodes.
    62  func (p *IntegrationTestNodePreparer) PrepareNodes(ctx context.Context, nextNodeIndex int) error {
    63  	numNodes := 0
    64  	for _, v := range p.countToStrategy {
    65  		numNodes += v.Count
    66  	}
    67  
    68  	klog.Infof("Making %d nodes", numNodes)
    69  	baseNode := &v1.Node{
    70  		ObjectMeta: metav1.ObjectMeta{
    71  			GenerateName: p.nodeNamePrefix,
    72  		},
    73  		Status: v1.NodeStatus{
    74  			Capacity: v1.ResourceList{
    75  				v1.ResourcePods:   *resource.NewQuantity(110, resource.DecimalSI),
    76  				v1.ResourceCPU:    resource.MustParse("4"),
    77  				v1.ResourceMemory: resource.MustParse("32Gi"),
    78  			},
    79  			Phase: v1.NodeRunning,
    80  			Conditions: []v1.NodeCondition{
    81  				{Type: v1.NodeReady, Status: v1.ConditionTrue},
    82  			},
    83  		},
    84  	}
    85  
    86  	if p.nodeSpec != nil {
    87  		baseNode = p.nodeSpec
    88  	}
    89  
    90  	for i := 0; i < numNodes; i++ {
    91  		var err error
    92  		for retry := 0; retry < retries; retry++ {
    93  			// Create nodes with the usual kubernetes.io/hostname label.
    94  			// For that we need to know the name in advance, if we want to
    95  			// do it in one request.
    96  			node := baseNode.DeepCopy()
    97  			name := node.Name
    98  			if name == "" {
    99  				name = node.GenerateName + rand.String(5)
   100  				node.Name = name
   101  			}
   102  			if node.Labels == nil {
   103  				node.Labels = make(map[string]string)
   104  			}
   105  			node.Labels["kubernetes.io/hostname"] = name
   106  			_, err = p.client.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{})
   107  			if err == nil {
   108  				break
   109  			}
   110  		}
   111  		if err != nil {
   112  			klog.Fatalf("Error creating node: %v", err)
   113  		}
   114  	}
   115  
   116  	nodes, err := waitListAllNodes(p.client)
   117  	if err != nil {
   118  		klog.Fatalf("Error listing nodes: %v", err)
   119  	}
   120  	index := nextNodeIndex
   121  	for _, v := range p.countToStrategy {
   122  		for i := 0; i < v.Count; i, index = i+1, index+1 {
   123  			if err := testutils.DoPrepareNode(ctx, p.client, &nodes.Items[index], v.Strategy); err != nil {
   124  				klog.Errorf("Aborting node preparation: %v", err)
   125  				return err
   126  			}
   127  		}
   128  	}
   129  	return nil
   130  }
   131  
   132  // CleanupNodes deletes existing test nodes.
   133  func (p *IntegrationTestNodePreparer) CleanupNodes(ctx context.Context) error {
   134  	// TODO(#93794): make CleanupNodes only clean up the nodes created by this
   135  	// IntegrationTestNodePreparer to make this more intuitive.
   136  	nodes, err := waitListAllNodes(p.client)
   137  	if err != nil {
   138  		klog.Fatalf("Error listing nodes: %v", err)
   139  	}
   140  	var errRet error
   141  	for i := range nodes.Items {
   142  		if err := p.client.CoreV1().Nodes().Delete(ctx, nodes.Items[i].Name, metav1.DeleteOptions{}); err != nil {
   143  			klog.Errorf("Error while deleting Node: %v", err)
   144  			errRet = err
   145  		}
   146  	}
   147  	return errRet
   148  }