Skip to content

Commit

Permalink
Go example that removes all S3 buckets with given prefix (#964)
Browse files Browse the repository at this point in the history
Go example that removes all S3 buckets with given prefix, including first removing all objects in the buckets
  • Loading branch information
Doug-AWS committed Feb 15, 2020
1 parent edf02e3 commit 9ecc72b
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 0 deletions.
75 changes: 75 additions & 0 deletions go/example_code/s3/delete-buckets-by-prefix/README.md
@@ -0,0 +1,75 @@
# AWS SDK for Go Code Examples for Amazon S3

## Purpose

This example demonstrates how to delete all of the Amazon S3 buckets you own that begin with a given prefix.

## Prerequisites

You must have an AWS account, and have your default credentials and AWS Region
configured as described in
[Configuring the AWS SDK for Go](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html)
in the AWS SDK for Go Developer Guide.

## Running the Code

### Syntax

`go run s3_delete_buckets -p` *PREFIX*

- *PREFIX* is the first characters of the names of the Amazon S3 buckets to delete.

For example, if you call `go run s3_delete_buckets.go -p dummy-`,
it first removes all of the objects in the Amazon S3 buckets with names starting with *dummy-*,
then deletes all of those S3 buckets.

### Notes

- We recommend that you grant this code least privilege,
or at most the minimum permissions required to perform the task.
For more information, see
[Grant Least Privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)
in the AWS Identity and Access Management User Guide.
- This code has not been tested in all Regions.
Some AWS services are available only in specific
[Regions](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
- Running this code might result in charges to your AWS account.

## Running the Unit Tests

Unit tests should delete any resources they create.
However, they might result in charges to your
AWS account.

The unit test:

1. Creates three S3 buckets,
with a name starting with *dummy-*,
followed by a GUID, and then the numbers 0-2.
2. Lists all of the buckets with a name starting with *dummy-*
3. Removes all objects in the S3 buckets with names starting with *dummy-*
4. Deletes all S3 buckets with names starting with *dummy-*
5. Lists all of the buckets with a name starting with *dummy-*

To run the unit test, enter:

`go test`

You should see something like the following,
where PATH is the path to folder containing the Go files:

```
PASS
ok PATH 6.593s
```

If you want to see any log messages, enter:

`go test -test.v`

You should see some additional log messages.
The last two lines should be similar to the previous output shown.

You can confirm it has deleted any resources it created by running:

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0
10 changes: 10 additions & 0 deletions go/example_code/s3/delete-buckets-by-prefix/metadata.yaml
@@ -0,0 +1,10 @@
---
created: 2020-02-14
files:
- path: s3_delete_buckets.go
apis:
- service: s3
operations:
- ListBuckets
- DeleteBucket
- WaitUntilBucketNotExists
102 changes: 102 additions & 0 deletions go/example_code/s3/delete-buckets-by-prefix/s3_delete_buckets.go
@@ -0,0 +1,102 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/
package main

import (
"flag"
"fmt"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

func deleteBucketsByPrefix(sess *session.Session, prefix string) error {
// Create Amazon S3 service client
svc := s3.New(sess)

// Empty list to hold names of S3 buckets with prefix
bucketList := make([]string, 0)

result, err := svc.ListBuckets(nil)
if err != nil {
return err
}

for _, b := range result.Buckets {
// Does bucket name start with prefix
if strings.HasPrefix(*b.Name, prefix) {
bucketList = append(bucketList, *b.Name)
}
}

for _, b := range bucketList {
// First delete any objects in the bucket
iter := s3manager.NewDeleteListIterator(svc, &s3.ListObjectsInput{
Bucket: aws.String(b),
})

err := s3manager.NewBatchDeleteWithClient(svc).Delete(aws.BackgroundContext(), iter)
if err != nil {
return err
}

_, err = svc.DeleteBucket(&s3.DeleteBucketInput{
Bucket: aws.String(b),
})
if err != nil {
return err
}

err = svc.WaitUntilBucketNotExists(&s3.HeadBucketInput{
Bucket: aws.String(b),
})
if err != nil {
return err
}
}

return nil
}

// Deletes any S3 buckets in the default AWS Region
// that start with the given text
//
// Usage:
// go run s3_delete_buckets -p PREFIX
func main() {
prefixPtr := flag.String("p", "", "The prefix of the buckets to delete")
flag.Parse()
prefix := *prefixPtr

if prefix == "" {
fmt.Println("You must supply a bucket prefix")
return
}

// Initialize a session that the SDK uses to load
// credentials from the shared credentials file (~/.aws/credentials)
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))

err := deleteBucketsByPrefix(sess, prefix)
if err != nil {
fmt.Println("Could not delete buckets with prefix " + prefix)
} else {
fmt.Println("Deleted buckets with prefix " + prefix)
}
}
146 changes: 146 additions & 0 deletions go/example_code/s3/delete-buckets-by-prefix/s3_delete_buckets_test.go
@@ -0,0 +1,146 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/
package main

import (
"strconv"
"strings"
"testing"
"time"

"github.com/google/uuid"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

func createBucket(sess *session.Session, bucketName string) error {
// Create Amazon S3 service client
svc := s3.New(sess)

// Create the S3 Bucket
_, err := svc.CreateBucket(&s3.CreateBucketInput{
Bucket: aws.String(bucketName),
})
if err != nil {
return err
}

// Wait until bucket is created before finishing
return svc.WaitUntilBucketExists(&s3.HeadBucketInput{
Bucket: aws.String(bucketName),
})
}

func populateBucket(sess *session.Session, bucket string) error {
s3Svc := s3.New(sess)

// Create an uploader with S3 client and default options
uploader := s3manager.NewUploaderWithClient(s3Svc)

// Add some dummy data to the bucket
text := "abc"
body := strings.NewReader(text)

upParams := &s3manager.UploadInput{
Bucket: &bucket,
Key: aws.String("dummy"),
Body: body,
}

_, err := uploader.Upload(upParams)
return err
}

// listBuckets lists the S3 buckets with the given prefix
func listBuckets(sess *session.Session, prefix string, t *testing.T) error {
// Create S3 service client
svc := s3.New(sess)

result, err := svc.ListBuckets(nil)
if err != nil {
t.Log("Could not list buckets")
return err
}

for _, b := range result.Buckets {
if strings.HasPrefix(*b.Name, prefix) {
t.Log(*b.Name)
}
}

return nil
}

func TestDeleteBuckets(t *testing.T) {
// When the test started
thisTime := time.Now()
nowString := thisTime.Format("20060102150405")
t.Log("Starting unit test at " + nowString)

// Initialize a session that the SDK uses to load
// credentials from the shared credentials file (~/.aws/credentials)
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))

// Create a unique GUID
id := uuid.New()
defaultName := id.String()

// Create 3 dummy buckets with prefix "dummy-"
prefix := "dummy-"

for i := 0; i < 3; i++ {
name := prefix + defaultName + strconv.Itoa(i)

err := createBucket(sess, name)
if err != nil {
t.Fatal("Could not create bucket: " + name)
}

t.Log("Created bucket " + name)

err = populateBucket(sess, name)
if err != nil {
t.Fatal("Could not populate bucket")
}
}

// List the buckets
t.Log("Buckets that start with " + prefix + ":")
err := listBuckets(sess, prefix, t)
if err != nil {
t.Fatal(err)
}

// Now delete them
err = deleteBucketsByPrefix(sess, prefix)
if err != nil {
t.Log("You might have to delete these buckets with:")
t.Log("go run s3_delete_buckets.go -p dummy-")
t.Fatal(err)
} else {
t.Log("Deleted buckets with prefix " + prefix)
}

// List the buckets
t.Log("Now here are your buckets that start with " + prefix + ":")
err = listBuckets(sess, prefix, t)
if err != nil {
t.Fatal(err)
}
}

0 comments on commit 9ecc72b

Please sign in to comment.