@@ -14,48 +14,70 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
- package framework
17
+ package benchmark
18
18
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "time"
22
23
23
24
v1 "k8s.io/api/core/v1"
24
- "k8s.io/apimachinery/pkg/api/resource"
25
25
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
26
"k8s.io/apimachinery/pkg/util/rand"
27
+ "k8s.io/apimachinery/pkg/util/wait"
27
28
clientset "k8s.io/client-go/kubernetes"
28
29
"k8s.io/klog/v2"
29
30
testutils "k8s.io/kubernetes/test/utils"
30
31
)
31
32
32
33
const (
33
- retries = 5
34
+ // createNodeRetries defines number of retries when creating nodes.
35
+ createNodeRetries = 5
36
+
37
+ // pollingInterval defines how often to poll when waiting for nodes to be created.
38
+ pollingInterval = 2 * time .Second
39
+
40
+ // singleCallTimeout is how long to try single API calls (like 'get' or 'list'). Used to prevent
41
+ // transient failures from failing tests.
42
+ singleCallTimeout = 5 * time .Minute
34
43
)
35
44
45
+ // NodeTemplate is responsible for creating a v1.Node instance that is ready
46
+ // to be sent to the API server.
47
+ type NodeTemplate interface {
48
+ // GetNodeTemplate returns a node template for one out of many different nodes.
49
+ // It gets called multiple times with an increasing index and a fixed count parameters.
50
+ // This number can, but doesn't have to be, used to modify parts of the node spec like
51
+ // for example a named reference to some other object.
52
+ GetNodeTemplate (index , count int ) (* v1.Node , error )
53
+ }
54
+
55
+ // StaticNodeTemplate returns an implementation of NodeTemplate for a fixed node that is the same regardless of the index.
56
+ func StaticNodeTemplate (node * v1.Node ) NodeTemplate {
57
+ return (* staticNodeTemplate )(node )
58
+ }
59
+
60
+ type staticNodeTemplate v1.Node
61
+
62
+ // GetNodeTemplate implements [NodeTemplate.GetNodeTemplate] by returning the same node
63
+ // for each call.
64
+ func (s * staticNodeTemplate ) GetNodeTemplate (index , count int ) (* v1.Node , error ) {
65
+ return (* v1 .Node )(s ), nil
66
+ }
67
+
36
68
// IntegrationTestNodePreparer holds configuration information for the test node preparer.
37
69
type IntegrationTestNodePreparer struct {
38
70
client clientset.Interface
39
71
countToStrategy []testutils.CountToStrategy
40
- nodeNamePrefix string
41
- nodeSpec * v1.Node
72
+ nodeTemplate NodeTemplate
42
73
}
43
74
44
- // NewIntegrationTestNodePreparer creates an IntegrationTestNodePreparer configured with defaults .
45
- func NewIntegrationTestNodePreparer (client clientset.Interface , countToStrategy []testutils.CountToStrategy , nodeNamePrefix string ) testutils.TestNodePreparer {
75
+ // NewIntegrationTestNodePreparer creates an IntegrationTestNodePreparer with a given nodeTemplate .
76
+ func NewIntegrationTestNodePreparer (client clientset.Interface , countToStrategy []testutils.CountToStrategy , nodeTemplate NodeTemplate ) testutils.TestNodePreparer {
46
77
return & IntegrationTestNodePreparer {
47
78
client : client ,
48
79
countToStrategy : countToStrategy ,
49
- nodeNamePrefix : nodeNamePrefix ,
50
- }
51
- }
52
-
53
- // NewIntegrationTestNodePreparerWithNodeSpec creates an IntegrationTestNodePreparer configured with nodespec.
54
- func NewIntegrationTestNodePreparerWithNodeSpec (client clientset.Interface , countToStrategy []testutils.CountToStrategy , nodeSpec * v1.Node ) testutils.TestNodePreparer {
55
- return & IntegrationTestNodePreparer {
56
- client : client ,
57
- countToStrategy : countToStrategy ,
58
- nodeSpec : nodeSpec ,
80
+ nodeTemplate : nodeTemplate ,
59
81
}
60
82
}
61
83
@@ -67,30 +89,13 @@ func (p *IntegrationTestNodePreparer) PrepareNodes(ctx context.Context, nextNode
67
89
}
68
90
69
91
klog .Infof ("Making %d nodes" , numNodes )
70
- baseNode := & v1.Node {
71
- ObjectMeta : metav1.ObjectMeta {
72
- GenerateName : p .nodeNamePrefix ,
73
- },
74
- Status : v1.NodeStatus {
75
- Capacity : v1.ResourceList {
76
- v1 .ResourcePods : * resource .NewQuantity (110 , resource .DecimalSI ),
77
- v1 .ResourceCPU : resource .MustParse ("4" ),
78
- v1 .ResourceMemory : resource .MustParse ("32Gi" ),
79
- },
80
- Phase : v1 .NodeRunning ,
81
- Conditions : []v1.NodeCondition {
82
- {Type : v1 .NodeReady , Status : v1 .ConditionTrue },
83
- },
84
- },
85
- }
86
-
87
- if p .nodeSpec != nil {
88
- baseNode = p .nodeSpec
89
- }
90
92
91
93
for i := 0 ; i < numNodes ; i ++ {
92
- var err error
93
- for retry := 0 ; retry < retries ; retry ++ {
94
+ baseNode , err := p .nodeTemplate .GetNodeTemplate (i , numNodes )
95
+ if err != nil {
96
+ return fmt .Errorf ("failed to get node template: %w" , err )
97
+ }
98
+ for retry := 0 ; retry < createNodeRetries ; retry ++ {
94
99
// Create nodes with the usual kubernetes.io/hostname label.
95
100
// For that we need to know the name in advance, if we want to
96
101
// do it in one request.
@@ -114,7 +119,7 @@ func (p *IntegrationTestNodePreparer) PrepareNodes(ctx context.Context, nextNode
114
119
}
115
120
}
116
121
117
- nodes , err := waitListAllNodes (p .client )
122
+ nodes , err := waitListAllNodes (ctx , p .client )
118
123
if err != nil {
119
124
return fmt .Errorf ("listing nodes: %w" , err )
120
125
}
@@ -133,7 +138,7 @@ func (p *IntegrationTestNodePreparer) PrepareNodes(ctx context.Context, nextNode
133
138
func (p * IntegrationTestNodePreparer ) CleanupNodes (ctx context.Context ) error {
134
139
// TODO(#93794): make CleanupNodes only clean up the nodes created by this
135
140
// IntegrationTestNodePreparer to make this more intuitive.
136
- nodes , err := waitListAllNodes (p .client )
141
+ nodes , err := waitListAllNodes (ctx , p .client )
137
142
if err != nil {
138
143
klog .Fatalf ("Error listing nodes: %v" , err )
139
144
}
@@ -146,3 +151,19 @@ func (p *IntegrationTestNodePreparer) CleanupNodes(ctx context.Context) error {
146
151
}
147
152
return errRet
148
153
}
154
+
155
+ // waitListAllNodes is a wrapper around listing nodes supporting retries.
156
+ func waitListAllNodes (ctx context.Context , c clientset.Interface ) (* v1.NodeList , error ) {
157
+ var nodes * v1.NodeList
158
+ var err error
159
+ if wait .PollUntilContextTimeout (ctx , pollingInterval , singleCallTimeout , true , func (ctx context.Context ) (bool , error ) {
160
+ nodes , err = c .CoreV1 ().Nodes ().List (ctx , metav1.ListOptions {})
161
+ if err != nil {
162
+ return false , err
163
+ }
164
+ return true , nil
165
+ }) != nil {
166
+ return nodes , err
167
+ }
168
+ return nodes , nil
169
+ }
0 commit comments