Add s3-delete-all command
This commit is contained in:
parent
dc497b546a
commit
50e7b59442
|
@ -0,0 +1,86 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/config"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
|
"github.com/aws/smithy-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
const cmdName = "s3-delete-all"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
cfg, err := config.LoadDefaultConfig(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
s3Client := s3.NewFromConfig(cfg)
|
||||||
|
|
||||||
|
var bucket string
|
||||||
|
flag.StringVar(&bucket, "bucket", "", "name of S3 bucket")
|
||||||
|
flag.Parse()
|
||||||
|
if bucket == "" {
|
||||||
|
log.Fatalf("usage: %s -bucket bucket", cmdName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete S3 objects
|
||||||
|
|
||||||
|
listObjectsInput := s3.ListObjectsV2Input{Bucket: aws.String(bucket), MaxKeys: 10_000}
|
||||||
|
listObjectsOutput, err := s3Client.ListObjectsV2(ctx, &listObjectsInput)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, object := range listObjectsOutput.Contents {
|
||||||
|
deleteObjectInput := s3.DeleteObjectInput{Bucket: aws.String(bucket), Key: object.Key}
|
||||||
|
_, err = s3Client.DeleteObject(ctx, &deleteObjectInput)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Deleted object %s", *object.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete S3 uploads and parts
|
||||||
|
|
||||||
|
listUploadsInput := s3.ListMultipartUploadsInput{Bucket: aws.String(bucket)}
|
||||||
|
listUploadsOutput, err := s3Client.ListMultipartUploads(ctx, &listUploadsInput)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if listObjectsOutput.IsTruncated {
|
||||||
|
log.Fatal("TODO: handle IsTruncated")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, upload := range listUploadsOutput.Uploads {
|
||||||
|
abortUploadInput := s3.AbortMultipartUploadInput{Bucket: aws.String(bucket), Key: upload.Key, UploadId: upload.UploadId}
|
||||||
|
_, err := s3Client.AbortMultipartUpload(ctx, &abortUploadInput)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
listPartsInput := s3.ListPartsInput{Bucket: aws.String(bucket), Key: upload.Key, UploadId: upload.UploadId}
|
||||||
|
listPartsOutput, err := s3Client.ListParts(ctx, &listPartsInput)
|
||||||
|
if err != nil {
|
||||||
|
var ae smithy.APIError
|
||||||
|
if errors.As(err, &ae) && ae.ErrorCode() == "NoSuchUpload" {
|
||||||
|
log.Printf("Ignoring upload not found (id = %s)", *upload.UploadId)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(listPartsOutput.Parts) > 0 {
|
||||||
|
log.Fatalf("some parts remain for key %s, upload %s (count = %d)", *upload.UploadId, *upload.Key, len(listPartsOutput.Parts))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Aborted upload %s", *upload.UploadId)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue