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) } }