Skip to content

Commit 092907a

Browse files
authored
🌱 e2e: properly label and cleanup created PVCs during e2e tests in prow (#3361)
* e2e: properly label and cleanup created PVCs during e2e tests in prow * fixes * fixup
1 parent 7602fa1 commit 092907a

File tree

7 files changed

+364
-50
lines changed

7 files changed

+364
-50
lines changed

‎go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc
4848
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
4949
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
5050
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
51+
github.com/dougm/pretty v0.0.0-20160325215624-add1dbc86daf h1:A2XbJkAuMMFy/9EftoubSKBUIyiOm6Z8+X5G7QpS6so=
52+
github.com/dougm/pretty v0.0.0-20160325215624-add1dbc86daf/go.mod h1:7NQ3kWOx2cZOSjtcveTa5nqupVr2s6/83sG+rTlI7uA=
5153
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
5254
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
5355
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=

‎hack/tools/boskosctl/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ func release(ctx context.Context, client *boskos.Client, resourceName, vSphereUs
364364
log.Info("Cleaning up vSphere")
365365
// Note: We intentionally want to skip clusterModule cleanup. If we run this too often we might hit race conditions
366366
// when other tests are creating cluster modules in parallel.
367-
if err := j.CleanupVSphere(ctx, []string{vSphereFolder}, []string{vSphereResourcePool}, []string{vSphereFolder}, true); err != nil {
367+
if err := j.CleanupVSphere(ctx, []string{vSphereFolder}, []string{vSphereResourcePool}, []string{vSphereFolder}, resourceName, true); err != nil {
368368
log.Info("Cleaning up vSphere failed")
369369

370370
// Try to release resource as dirty.

‎hack/tools/janitor/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func run(ctx context.Context) error {
162162
j := janitor.NewJanitor(vSphereClients, false)
163163

164164
log.Info("Cleaning up vSphere")
165-
if err := j.CleanupVSphere(ctx, []string{folder.(string)}, []string{resourcePool.(string)}, []string{folder.(string)}, false); err != nil {
165+
if err := j.CleanupVSphere(ctx, []string{folder.(string)}, []string{resourcePool.(string)}, []string{folder.(string)}, res.Name, false); err != nil {
166166
log.Info("Cleaning up vSphere failed")
167167

168168
// Intentionally keep this resource in cleaning state. The reaper will move it from cleaning to dirty

‎hack/tools/pkg/janitor/janitor.go

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ import (
2525
"strings"
2626

2727
"github.com/pkg/errors"
28+
cnstypes "github.com/vmware/govmomi/cns/types"
2829
"github.com/vmware/govmomi/object"
2930
govmomicluster "github.com/vmware/govmomi/vapi/cluster"
3031
"github.com/vmware/govmomi/vim25/mo"
3132
"github.com/vmware/govmomi/vim25/types"
3233
kerrors "k8s.io/apimachinery/pkg/util/errors"
34+
"k8s.io/klog/v2"
3335
ctrl "sigs.k8s.io/controller-runtime"
3436
)
3537

@@ -52,8 +54,12 @@ type virtualMachine struct {
5254
object *object.VirtualMachine
5355
}
5456

57+
// boskosResourceLabel is used to identify volumes created in e2e tests.
58+
// The value should contain the boskos resource name.
59+
const boskosResourceLabel = "capv-e2e-test-boskos-resource"
60+
5561
// CleanupVSphere cleans up vSphere VMs, folders and resource pools.
56-
func (s *Janitor) CleanupVSphere(ctx context.Context, folders, resourcePools, vmFolders []string, skipClusterModule bool) error {
62+
func (s *Janitor) CleanupVSphere(ctx context.Context, folders, resourcePools, vmFolders []string, boskosResourceName string, skipClusterModule bool) error {
5763
errList := []error{}
5864

5965
// Delete vms to cleanup folders and resource pools.
@@ -86,6 +92,11 @@ func (s *Janitor) CleanupVSphere(ctx context.Context, folders, resourcePools, vm
8692
return errors.Wrap(err, "cleaning up folders")
8793
}
8894

95+
// Delete CNS volumes.
96+
if err := s.DeleteCNSVolumes(ctx, boskosResourceName); err != nil {
97+
return errors.Wrap(err, "cleaning up volumes")
98+
}
99+
89100
if skipClusterModule {
90101
return nil
91102
}
@@ -197,6 +208,118 @@ func (s *Janitor) deleteVSphereVMs(ctx context.Context, folder string) error {
197208
return nil
198209
}
199210

211+
// DeleteCNSVolumes deletes all volumes from tests.
212+
func (s *Janitor) DeleteCNSVolumes(ctx context.Context, boskosResourceName string) error {
213+
log := ctrl.LoggerFrom(ctx).WithName("volumes")
214+
ctx = ctrl.LoggerInto(ctx, log)
215+
216+
log.Info("Deleting volumes")
217+
218+
type cnsVolumeToDelete struct {
219+
volumeID cnstypes.CnsVolumeId
220+
pvcName string
221+
pvcNamespace string
222+
}
223+
volumesToDelete := []cnsVolumeToDelete{}
224+
225+
queryFilter := cnstypes.CnsQueryFilter{
226+
Labels: []types.KeyValue{
227+
{
228+
Key: boskosResourceLabel,
229+
Value: boskosResourceName,
230+
},
231+
},
232+
}
233+
234+
for {
235+
res, err := s.vSphereClients.CNS.QueryVolume(ctx, queryFilter)
236+
if err != nil {
237+
return err
238+
}
239+
240+
for _, volume := range res.Volumes {
241+
var pvcMetadata *cnstypes.CnsKubernetesEntityMetadata
242+
for _, meta := range volume.Metadata.EntityMetadata {
243+
k8sMetadata, ok := meta.(*cnstypes.CnsKubernetesEntityMetadata)
244+
if !ok {
245+
continue
246+
}
247+
if k8sMetadata.EntityType != string(cnstypes.CnsKubernetesEntityTypePVC) {
248+
continue
249+
}
250+
pvcMetadata = k8sMetadata
251+
}
252+
253+
if pvcMetadata == nil {
254+
// Ignoring non-PVC volumes.
255+
continue
256+
}
257+
258+
var matchesBoskosResourcename bool
259+
// Check again that the volume has a matching label.
260+
for _, v := range pvcMetadata.Labels {
261+
if v.Key != boskosResourceLabel {
262+
continue
263+
}
264+
if v.Value != boskosResourceName {
265+
continue
266+
}
267+
matchesBoskosResourcename = true
268+
}
269+
270+
// Ignore not matching volume.
271+
if !matchesBoskosResourcename {
272+
continue
273+
}
274+
275+
volumesToDelete = append(volumesToDelete, cnsVolumeToDelete{
276+
volumeID: volume.VolumeId,
277+
pvcName: pvcMetadata.EntityName,
278+
pvcNamespace: pvcMetadata.Namespace,
279+
})
280+
}
281+
282+
if res.Cursor.Offset == res.Cursor.TotalRecords || len(res.Volumes) == 0 {
283+
break
284+
}
285+
286+
queryFilter.Cursor = &res.Cursor
287+
}
288+
289+
if len(volumesToDelete) == 0 {
290+
log.Info("No CNS Volumes to delete")
291+
return nil
292+
}
293+
294+
deleteTasks := []*object.Task{}
295+
for _, volume := range volumesToDelete {
296+
log := log.WithValues("volumeID", volume.volumeID, "PersistentVolumeClaim", klog.KRef(volume.pvcNamespace, volume.pvcName))
297+
298+
log.Info("Deleting CNS Volume in vSphere")
299+
300+
if s.dryRun {
301+
// Skipping actual delete on dryRun.
302+
continue
303+
}
304+
305+
// Trigger deletion of the CNS Volume
306+
task, err := s.vSphereClients.CNS.DeleteVolume(ctx, []cnstypes.CnsVolumeId{volume.volumeID}, true)
307+
if err != nil {
308+
return errors.Wrap(err, "failed to create CNS Volume deletion task")
309+
}
310+
311+
log.Info("Created CNS Volume deletion task", "task", task.Reference().Value)
312+
deleteTasks = append(deleteTasks, task)
313+
}
314+
315+
// Wait for all delete tasks to succeed.
316+
if err := waitForTasksFinished(ctx, deleteTasks, false); err != nil {
317+
return errors.Wrap(err, "failed to wait for CNS Volume deletion tasks to finish")
318+
}
319+
320+
return nil
321+
}
322+
200323
// deleteObjectChildren deletes all child objects in a given object in vSphere if they don't
201324
// contain any virtual machine.
202325
// An object only gets deleted if:

0 commit comments

Comments
 (0)