in internal/testutil/storage_cleaner.go [65:131]
func DeleteBucketIfExists(ctx context.Context, client *storage.Client, bucket string) error {
b := client.Bucket(bucket)
// Check if the bucket does not exist, return nil.
if _, err := b.Attrs(ctx); err != nil {
return nil
}
// Delete all of the elements in the already existent bucket, including noncurrent objects.
it := b.Objects(ctx, &storage.Query{
// Versions true to output all generations of objects.
Versions: true,
})
for {
attrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return fmt.Errorf("Bucket.Objects(%q): %v", bucket, err)
}
obj := b.Object(attrs.Name)
// Objects with a hold must have the hold released
if attrs.EventBasedHold || attrs.TemporaryHold {
if _, err := obj.Update(ctx, storage.ObjectAttrsToUpdate{
TemporaryHold: false,
EventBasedHold: false,
}); err != nil {
return fmt.Errorf("Bucket(%q).Object(%q).Update: %v", bucket, attrs.Name, err)
}
}
// Objects with a retention policy must must have the policy removed.
if attrs.Retention != nil {
_, err = obj.OverrideUnlockedRetention(true).Update(ctx, storage.ObjectAttrsToUpdate{
Retention: &storage.ObjectRetention{},
})
if err != nil {
return fmt.Errorf("failed to remove retention from object(%q): %v", attrs.Name, err)
}
}
if err := obj.Generation(attrs.Generation).Delete(ctx); err != nil {
return fmt.Errorf("Bucket(%q).Object(%q).Delete: %v", bucket, attrs.Name, err)
}
}
// Then delete the bucket itself.
if err := b.Delete(ctx); err != nil {
return fmt.Errorf("Bucket.Delete(%q): %v", bucket, err)
}
// Waits for a bucket to no longer exist, as it can take time to propagate
// Errors after 10 successful attempts at retrieving the bucket's attrs
retries := 10
delay := 10 * time.Second
for i := 0; i < retries; i++ {
if _, err := b.Attrs(ctx); err != nil {
// Deletion successful.
return nil
}
// Deletion not complete.
time.Sleep(delay)
}
return fmt.Errorf("failed to delete bucket %q", bucket)
}