Skip to content

Commit 2021926

Browse files
committed
[AWS/S3] Fix: S3 destroy all object versions before destroying bucket
1 parent 0c3e161 commit 2021926

File tree

2 files changed

+88
-3
lines changed

2 files changed

+88
-3
lines changed

.goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ project_name: reka
33
builds:
44
- env:
55
- CGO_ENABLED=0
6-
binary: gophie
6+
binary: reka
77
goos:
88
- windows
99
- darwin

provider/aws/s3.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import (
1414
"github.com/mensaah/reka/resource"
1515
)
1616

17+
type Object struct {
18+
Key *string
19+
VersionId *string
20+
}
21+
1722
func getS3BucketRegion(cfg aws.Config, bucketName string) (string, error) {
1823

1924
region, err := s3manager.GetBucketRegion(context.TODO(), s3.NewFromConfig(cfg), bucketName)
@@ -94,18 +99,98 @@ func getAllS3Buckets(cfg aws.Config) ([]*resource.Resource, error) {
9499
return buckets, nil
95100
}
96101

102+
func getAllObjects(svc *s3.Client, bucketName *string, isVersioned bool) ([]*Object, error) {
103+
var objects []*Object
104+
if !isVersioned {
105+
// Set the parameters based on the CLI flag inputs.
106+
params := &s3.ListObjectsV2Input{
107+
Bucket: bucketName,
108+
}
109+
// Create the Paginator for the ListObjectsV2 operation.
110+
p := s3.NewListObjectsV2Paginator(svc, params, func(o *s3.ListObjectsV2PaginatorOptions) {
111+
if v := int32(0); v != 0 {
112+
o.Limit = v
113+
}
114+
})
115+
116+
// Iterate through the S3 object pages, printing each object returned.
117+
var i int
118+
log.Println("Objects:")
119+
for p.HasMorePages() {
120+
i++
121+
// Next Page takes a new context for each page retrieval. This is where
122+
// you could add timeouts or deadlines.
123+
page, err := p.NextPage(context.TODO())
124+
if err != nil {
125+
log.Fatalf("failed to get page %v, %v", i, err)
126+
}
127+
128+
// Log the objects found
129+
for _, obj := range page.Contents {
130+
fmt.Println("Object:", *obj.Key)
131+
objects = append(objects, &Object{Key: obj.Key})
132+
}
133+
}
134+
return objects, nil
135+
}
136+
137+
p, err := svc.ListObjectVersions(context.TODO(), &s3.ListObjectVersionsInput{
138+
Bucket: bucketName,
139+
})
140+
for _, obj := range p.Versions {
141+
s3Logger.Debugf("Bucket %s object %s version %s", *bucketName, *obj.Key, *obj.VersionId)
142+
objects = append(objects, &Object{
143+
Key: obj.Key,
144+
VersionId: obj.VersionId,
145+
})
146+
}
147+
for _, obj := range p.DeleteMarkers {
148+
s3Logger.Debugf("Bucket %s object %s DeleteMarker %s", *bucketName, *obj.Key, *obj.VersionId)
149+
objects = append(objects, &Object{
150+
Key: obj.Key,
151+
VersionId: obj.VersionId,
152+
})
153+
}
154+
return objects, err
155+
}
156+
97157
// Empties a Bucket
98-
func emptyBucket(svc *s3.Client, bucket *resource.Resource) error {
158+
func emptyBucket(svc *s3.Client, bucketName string) error {
159+
versioningResult, err := svc.GetBucketVersioning(context.TODO(), &s3.GetBucketVersioningInput{
160+
Bucket: &bucketName,
161+
})
162+
if err != nil {
163+
return err
164+
}
165+
166+
objects, err := getAllObjects(svc, &bucketName, versioningResult.Status == s3Types.BucketVersioningStatusEnabled)
167+
168+
for _, obj := range objects {
169+
deleteParams := &s3.DeleteObjectInput{
170+
Bucket: &bucketName,
171+
Key: obj.Key,
172+
VersionId: obj.VersionId,
173+
}
174+
_, err = svc.DeleteObject(context.TODO(), deleteParams)
175+
if err != nil {
176+
log.Errorf("Failed to delete object %s: %s", *obj.Key, err.Error())
177+
}
178+
}
99179
return nil
100180
}
101181

102182
// Destroys a Single Bucket
103183
func destroyBucket(svc *s3.Client, bucket *resource.Resource) error {
184+
err := emptyBucket(svc, bucket.UUID)
185+
if err != nil {
186+
return err
187+
}
188+
104189
input := &s3.DeleteBucketInput{
105190
Bucket: aws.String(bucket.UUID),
106191
}
107192

108-
_, err := svc.DeleteBucket(context.TODO(), input)
193+
_, err = svc.DeleteBucket(context.TODO(), input)
109194
if err != nil {
110195
return err
111196
}

0 commit comments

Comments
 (0)