@@ -77,69 +77,81 @@ type Nodes struct {
77
77
var pluginPermissions string
78
78
79
79
// NewNodes selects nodes to run the test on.
80
+ //
81
+ // Call this outside of ginkgo.It, then use the instance inside ginkgo.It.
80
82
func NewNodes (f * framework.Framework , minNodes , maxNodes int ) * Nodes {
81
83
nodes := & Nodes {}
82
84
ginkgo .BeforeEach (func (ctx context.Context ) {
83
-
84
- ginkgo .By ("selecting nodes" )
85
- // The kubelet plugin is harder. We deploy the builtin manifest
86
- // after patching in the driver name and all nodes on which we
87
- // want the plugin to run.
88
- //
89
- // Only a subset of the nodes are picked to avoid causing
90
- // unnecessary load on a big cluster.
91
- nodeList , err := e2enode .GetBoundedReadySchedulableNodes (ctx , f .ClientSet , maxNodes )
92
- framework .ExpectNoError (err , "get nodes" )
93
- numNodes := int32 (len (nodeList .Items ))
94
- if int (numNodes ) < minNodes {
95
- e2eskipper .Skipf ("%d ready nodes required, only have %d" , minNodes , numNodes )
96
- }
97
- nodes .NodeNames = nil
98
- for _ , node := range nodeList .Items {
99
- nodes .NodeNames = append (nodes .NodeNames , node .Name )
100
- }
101
- sort .Strings (nodes .NodeNames )
102
- framework .Logf ("testing on nodes %v" , nodes .NodeNames )
103
-
104
- // Watch claims in the namespace. This is useful for monitoring a test
105
- // and enables additional sanity checks.
106
- claimInformer := resourceapiinformer .NewResourceClaimInformer (f .ClientSet , f .Namespace .Name , 100 * time .Hour /* resync */ , nil )
107
- cancelCtx , cancel := context .WithCancelCause (context .Background ())
108
- var wg sync.WaitGroup
109
- ginkgo .DeferCleanup (func () {
110
- cancel (errors .New ("test has completed" ))
111
- wg .Wait ()
112
- })
113
- _ , err = claimInformer .AddEventHandler (cache.ResourceEventHandlerFuncs {
114
- AddFunc : func (obj any ) {
115
- defer ginkgo .GinkgoRecover ()
116
- claim := obj .(* resourceapi.ResourceClaim )
117
- framework .Logf ("New claim:\n %s" , format .Object (claim , 1 ))
118
- validateClaim (claim )
119
- },
120
- UpdateFunc : func (oldObj , newObj any ) {
121
- defer ginkgo .GinkgoRecover ()
122
- oldClaim := oldObj .(* resourceapi.ResourceClaim )
123
- newClaim := newObj .(* resourceapi.ResourceClaim )
124
- framework .Logf ("Updated claim:\n %s\n Diff:\n %s" , format .Object (newClaim , 1 ), cmp .Diff (oldClaim , newClaim ))
125
- validateClaim (newClaim )
126
- },
127
- DeleteFunc : func (obj any ) {
128
- defer ginkgo .GinkgoRecover ()
129
- claim := obj .(* resourceapi.ResourceClaim )
130
- framework .Logf ("Deleted claim:\n %s" , format .Object (claim , 1 ))
131
- },
132
- })
133
- framework .ExpectNoError (err , "AddEventHandler" )
134
- wg .Add (1 )
135
- go func () {
136
- defer wg .Done ()
137
- claimInformer .Run (cancelCtx .Done ())
138
- }()
85
+ nodes .init (ctx , f , minNodes , maxNodes )
139
86
})
140
87
return nodes
141
88
}
142
89
90
+ // NewNodesNow is a variant of NewNodes which can be used inside a ginkgo.It.
91
+ func NewNodesNow (ctx context.Context , f * framework.Framework , minNodes , maxNodes int ) * Nodes {
92
+ nodes := & Nodes {}
93
+ nodes .init (ctx , f , minNodes , maxNodes )
94
+ return nodes
95
+ }
96
+
97
+ func (nodes * Nodes ) init (ctx context.Context , f * framework.Framework , minNodes , maxNodes int ) {
98
+ ginkgo .By ("selecting nodes" )
99
+ // The kubelet plugin is harder. We deploy the builtin manifest
100
+ // after patching in the driver name and all nodes on which we
101
+ // want the plugin to run.
102
+ //
103
+ // Only a subset of the nodes are picked to avoid causing
104
+ // unnecessary load on a big cluster.
105
+ nodeList , err := e2enode .GetBoundedReadySchedulableNodes (ctx , f .ClientSet , maxNodes )
106
+ framework .ExpectNoError (err , "get nodes" )
107
+ numNodes := int32 (len (nodeList .Items ))
108
+ if int (numNodes ) < minNodes {
109
+ e2eskipper .Skipf ("%d ready nodes required, only have %d" , minNodes , numNodes )
110
+ }
111
+ nodes .NodeNames = nil
112
+ for _ , node := range nodeList .Items {
113
+ nodes .NodeNames = append (nodes .NodeNames , node .Name )
114
+ }
115
+ sort .Strings (nodes .NodeNames )
116
+ framework .Logf ("testing on nodes %v" , nodes .NodeNames )
117
+
118
+ // Watch claims in the namespace. This is useful for monitoring a test
119
+ // and enables additional sanity checks.
120
+ claimInformer := resourceapiinformer .NewResourceClaimInformer (f .ClientSet , f .Namespace .Name , 100 * time .Hour /* resync */ , nil )
121
+ cancelCtx , cancel := context .WithCancelCause (context .Background ())
122
+ var wg sync.WaitGroup
123
+ ginkgo .DeferCleanup (func () {
124
+ cancel (errors .New ("test has completed" ))
125
+ wg .Wait ()
126
+ })
127
+ _ , err = claimInformer .AddEventHandler (cache.ResourceEventHandlerFuncs {
128
+ AddFunc : func (obj any ) {
129
+ defer ginkgo .GinkgoRecover ()
130
+ claim := obj .(* resourceapi.ResourceClaim )
131
+ framework .Logf ("New claim:\n %s" , format .Object (claim , 1 ))
132
+ validateClaim (claim )
133
+ },
134
+ UpdateFunc : func (oldObj , newObj any ) {
135
+ defer ginkgo .GinkgoRecover ()
136
+ oldClaim := oldObj .(* resourceapi.ResourceClaim )
137
+ newClaim := newObj .(* resourceapi.ResourceClaim )
138
+ framework .Logf ("Updated claim:\n %s\n Diff:\n %s" , format .Object (newClaim , 1 ), cmp .Diff (oldClaim , newClaim ))
139
+ validateClaim (newClaim )
140
+ },
141
+ DeleteFunc : func (obj any ) {
142
+ defer ginkgo .GinkgoRecover ()
143
+ claim := obj .(* resourceapi.ResourceClaim )
144
+ framework .Logf ("Deleted claim:\n %s" , format .Object (claim , 1 ))
145
+ },
146
+ })
147
+ framework .ExpectNoError (err , "AddEventHandler" )
148
+ wg .Add (1 )
149
+ go func () {
150
+ defer wg .Done ()
151
+ claimInformer .Run (cancelCtx .Done ())
152
+ }()
153
+ }
154
+
143
155
func validateClaim (claim * resourceapi.ResourceClaim ) {
144
156
// The apiserver doesn't enforce that a claim always has a finalizer
145
157
// while being allocated. This is a convention that whoever allocates a
@@ -153,28 +165,43 @@ func validateClaim(claim *resourceapi.ResourceClaim) {
153
165
// NewDriver sets up controller (as client of the cluster) and
154
166
// kubelet plugin (via proxy) before the test runs. It cleans
155
167
// up after the test.
168
+ //
169
+ // Call this outside of ginkgo.It, then use the instance inside ginkgo.It.
156
170
func NewDriver (f * framework.Framework , nodes * Nodes , configureResources func () app.Resources , devicesPerNode ... map [string ]map [resourceapi.QualifiedName ]resourceapi.DeviceAttribute ) * Driver {
157
- d := & Driver {
158
- f : f ,
159
- fail : map [MethodInstance ]bool {},
160
- callCounts : map [MethodInstance ]int64 {},
161
- NodeV1alpha3 : true ,
162
- }
171
+ d := NewDriverInstance (f )
163
172
164
173
ginkgo .BeforeEach (func () {
165
- resources := configureResources ()
166
- if len (resources .Nodes ) == 0 {
167
- // This always has to be set because the driver might
168
- // not run on all nodes.
169
- resources .Nodes = nodes .NodeNames
170
- }
171
- ginkgo .DeferCleanup (d .IsGone ) // Register first so it gets called last.
172
- d .SetUp (nodes , resources , devicesPerNode ... )
173
- ginkgo .DeferCleanup (d .TearDown )
174
+ d .Run (nodes , configureResources , devicesPerNode ... )
174
175
})
175
176
return d
176
177
}
177
178
179
+ // NewDriverInstance is a variant of NewDriver where the driver is inactive and must
180
+ // be started explicitly with Run. May be used inside ginkgo.It.
181
+ func NewDriverInstance (f * framework.Framework ) * Driver {
182
+ d := & Driver {
183
+ f : f ,
184
+ fail : map [MethodInstance ]bool {},
185
+ callCounts : map [MethodInstance ]int64 {},
186
+ NodeV1alpha3 : true ,
187
+ parameterMode : parameterModeStructured ,
188
+ }
189
+ d .initName ()
190
+ return d
191
+ }
192
+
193
+ func (d * Driver ) Run (nodes * Nodes , configureResources func () app.Resources , devicesPerNode ... map [string ]map [resourceapi.QualifiedName ]resourceapi.DeviceAttribute ) {
194
+ resources := configureResources ()
195
+ if len (resources .Nodes ) == 0 {
196
+ // This always has to be set because the driver might
197
+ // not run on all nodes.
198
+ resources .Nodes = nodes .NodeNames
199
+ }
200
+ ginkgo .DeferCleanup (d .IsGone ) // Register first so it gets called last.
201
+ d .SetUp (nodes , resources , devicesPerNode ... )
202
+ ginkgo .DeferCleanup (d .TearDown )
203
+ }
204
+
178
205
type MethodInstance struct {
179
206
Nodename string
180
207
FullMethod string
@@ -215,25 +242,23 @@ const (
215
242
parameterModeStructured parameterMode = "structured" // allocation through scheduler
216
243
)
217
244
245
+ func (d * Driver ) initName () {
246
+ d .Name = d .f .UniqueName + d .NameSuffix + ".k8s.io"
247
+ }
248
+
218
249
func (d * Driver ) SetUp (nodes * Nodes , resources app.Resources , devicesPerNode ... map [string ]map [resourceapi.QualifiedName ]resourceapi.DeviceAttribute ) {
219
- ginkgo .By (fmt .Sprintf ("deploying driver on nodes %v" , nodes .NodeNames ))
250
+ d .initName ()
251
+ ginkgo .By (fmt .Sprintf ("deploying driver %s on nodes %v" , d .Name , nodes .NodeNames ))
220
252
d .Nodes = make (map [string ]KubeletPlugin )
221
- d .Name = d .f .UniqueName + d .NameSuffix + ".k8s.io"
222
253
resources .DriverName = d .Name
223
254
224
255
ctx , cancel := context .WithCancel (context .Background ())
225
- if d .NameSuffix != "" {
226
- logger := klog .FromContext (ctx )
227
- logger = klog .LoggerWithName (logger , "instance" + d .NameSuffix )
228
- ctx = klog .NewContext (ctx , logger )
229
- }
256
+ logger := klog .FromContext (ctx )
257
+ logger = klog .LoggerWithValues (logger , "driverName" , d .Name )
258
+ ctx = klog .NewContext (ctx , logger )
230
259
d .ctx = ctx
231
260
d .cleanup = append (d .cleanup , cancel )
232
261
233
- if d .parameterMode == "" {
234
- d .parameterMode = parameterModeStructured
235
- }
236
-
237
262
switch d .parameterMode {
238
263
case parameterModeClassicDRA :
239
264
// The controller is easy: we simply connect to the API server.
@@ -387,7 +412,7 @@ func (d *Driver) SetUp(nodes *Nodes, resources app.Resources, devicesPerNode ...
387
412
// Here we merely use impersonation, which is faster.
388
413
driverClient := d .impersonateKubeletPlugin (& pod )
389
414
390
- logger := klog .LoggerWithValues (klog .LoggerWithName (klog . Background () , "kubelet plugin" ), "node" , pod .Spec .NodeName , "pod" , klog .KObj (& pod ))
415
+ logger := klog .LoggerWithValues (klog .LoggerWithName (logger , "kubelet- plugin" ), "node" , pod .Spec .NodeName , "pod" , klog .KObj (& pod ))
391
416
loggerCtx := klog .NewContext (ctx , logger )
392
417
fileOps := app.FileOperations {
393
418
Create : func (name string , content []byte ) error {
0 commit comments