k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/common/wait_for_generic_k8s_object.go (about) 1 /* 2 Copyright 2023 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 common 18 19 import ( 20 "context" 21 "time" 22 23 "k8s.io/apimachinery/pkg/runtime/schema" 24 "k8s.io/klog/v2" 25 "k8s.io/perf-tests/clusterloader2/pkg/measurement" 26 measurementutil "k8s.io/perf-tests/clusterloader2/pkg/measurement/util" 27 "k8s.io/perf-tests/clusterloader2/pkg/util" 28 ) 29 30 const ( 31 defaultWaitForGenericK8sObjectsTimeout = 30 * time.Minute 32 defaultWaitForGenericK8sObjectsInterval = 30 * time.Second 33 waitForGenericK8sObjectsMeasurementName = "WaitForGenericK8sObjects" 34 ) 35 36 func init() { 37 if err := measurement.Register(waitForGenericK8sObjectsMeasurementName, createWaitForGenericK8sObjectsMeasurement); err != nil { 38 klog.Fatalf("Cannot register %s: %v", waitForGenericK8sObjectsMeasurementName, err) 39 } 40 } 41 42 func createWaitForGenericK8sObjectsMeasurement() measurement.Measurement { 43 return &waitForGenericK8sObjectsMeasurement{} 44 } 45 46 type waitForGenericK8sObjectsMeasurement struct{} 47 48 // Execute waits until desired number of k8s objects reached given conditions. 49 // Conditions can denote either success or failure. The measurement assumes the 50 // k8s object has a status.conditions field, which contains a []metav1.Condition. 51 // More here: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties 52 // Measurement will timeout if not enough objects have required conditions. 53 func (w *waitForGenericK8sObjectsMeasurement) Execute(config *measurement.Config) ([]measurement.Summary, error) { 54 groupVersionResource, err := getGroupVersionResource(config.Params) 55 if err != nil { 56 return nil, err 57 } 58 namespaces, err := getNamespaces(config.ClusterFramework.GetAutomanagedNamespacePrefix(), config.Params) 59 if err != nil { 60 return nil, err 61 } 62 timeout, err := util.GetDurationOrDefault(config.Params, "timeout", defaultWaitForGenericK8sObjectsTimeout) 63 if err != nil { 64 return nil, err 65 } 66 refreshInterval, err := util.GetDurationOrDefault(config.Params, "refreshInterval", defaultWaitForGenericK8sObjectsInterval) 67 if err != nil { 68 return nil, err 69 } 70 successfulConditions, err := util.GetStringArray(config.Params, "successfulConditions") 71 if err != nil { 72 return nil, err 73 } 74 failedConditions, err := util.GetStringArray(config.Params, "failedConditions") 75 if err != nil { 76 return nil, err 77 } 78 minDesiredObjectCount, err := util.GetInt(config.Params, "minDesiredObjectCount") 79 if err != nil { 80 return nil, err 81 } 82 maxFailedObjectCount, err := util.GetInt(config.Params, "maxFailedObjectCount") 83 if err != nil { 84 return nil, err 85 } 86 87 dynamicClient := config.ClusterFramework.GetDynamicClients().GetClient() 88 ctx, cancel := context.WithTimeout(context.TODO(), timeout) 89 defer cancel() 90 91 options := &measurementutil.WaitForGenericK8sObjectsOptions{ 92 GroupVersionResource: groupVersionResource, 93 Namespaces: namespaces, 94 SuccessfulConditions: successfulConditions, 95 FailedConditions: failedConditions, 96 MinDesiredObjectCount: minDesiredObjectCount, 97 MaxFailedObjectCount: maxFailedObjectCount, 98 CallerName: w.String(), 99 WaitInterval: refreshInterval, 100 } 101 return nil, measurementutil.WaitForGenericK8sObjects(ctx, dynamicClient, options) 102 } 103 104 // Dispose cleans up after the measurement. 105 func (*waitForGenericK8sObjectsMeasurement) Dispose() {} 106 107 // String returns a string representation of the measurement. 108 func (*waitForGenericK8sObjectsMeasurement) String() string { 109 return waitForGenericK8sObjectsMeasurementName 110 } 111 112 func getGroupVersionResource(params map[string]interface{}) (schema.GroupVersionResource, error) { 113 group, err := util.GetString(params, "objectGroup") 114 if err != nil { 115 return schema.GroupVersionResource{}, err 116 } 117 version, err := util.GetString(params, "objectVersion") 118 if err != nil { 119 return schema.GroupVersionResource{}, err 120 } 121 resource, err := util.GetString(params, "objectResource") 122 if err != nil { 123 return schema.GroupVersionResource{}, err 124 } 125 126 return schema.GroupVersionResource{ 127 Group: group, 128 Version: version, 129 Resource: resource, 130 }, nil 131 } 132 133 func getNamespaces(namespacesPrefix string, params map[string]interface{}) (measurementutil.NamespacesRange, error) { 134 namespaceRange, err := util.GetMap(params, "namespaceRange") 135 if err != nil { 136 return measurementutil.NamespacesRange{}, err 137 } 138 min, err := util.GetInt(namespaceRange, "min") 139 if err != nil { 140 return measurementutil.NamespacesRange{}, err 141 } 142 max, err := util.GetInt(namespaceRange, "max") 143 if err != nil { 144 return measurementutil.NamespacesRange{}, err 145 } 146 147 return measurementutil.NamespacesRange{ 148 Prefix: namespacesPrefix, 149 Min: min, 150 Max: max, 151 }, nil 152 }