From 6d838ed76c44abe0e2f8d6c89ab3f50d5ea068c3 Mon Sep 17 00:00:00 2001 From: "Collin J. Doering" Date: Tue, 1 Oct 2019 11:46:34 -0400 Subject: [PATCH] Allow s3 backends to contain more then 1000 workspaces * backend/remote-state/s3/backend_state.go: Prior to this commit, the terraform s3 backend did not paginate calls to s3 when finding workspaces, which resulted in workspaces 'disappearing' once they are switched away from, even though the state file still exists. This is due to the ListBucket operation defaulting MaxItems to 1000, so terraform s3 backends that contained more then 1000 workspaces did not function as expected. This rectifies this situation by paginating calls to s3 when finding workspaces. Signed-off-by: Collin J. Doering --- backend/remote-state/s3/backend_state.go | 30 +++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/backend/remote-state/s3/backend_state.go b/backend/remote-state/s3/backend_state.go index 646932476..861c284b4 100644 --- a/backend/remote-state/s3/backend_state.go +++ b/backend/remote-state/s3/backend_state.go @@ -18,6 +18,8 @@ import ( ) func (b *Backend) Workspaces() ([]string, error) { + const maxKeys = 1000 + prefix := "" if b.workspaceKeyPrefix != "" { @@ -25,24 +27,24 @@ func (b *Backend) Workspaces() ([]string, error) { } params := &s3.ListObjectsInput{ - Bucket: &b.bucketName, - Prefix: aws.String(prefix), - } - - resp, err := b.s3Client.ListObjects(params) - if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == s3.ErrCodeNoSuchBucket { - return nil, fmt.Errorf(errS3NoSuchBucket, err) - } - return nil, err + Bucket: &b.bucketName, + Prefix: aws.String(prefix), + MaxKeys: aws.Int64(maxKeys), } wss := []string{backend.DefaultStateName} - for _, obj := range resp.Contents { - ws := b.keyEnv(*obj.Key) - if ws != "" { - wss = append(wss, ws) + err := b.s3Client.ListObjectsPages(params, func(page *s3.ListObjectsOutput, lastPage bool) bool { + for _, obj := range page.Contents { + ws := b.keyEnv(*obj.Key) + if ws != "" { + wss = append(wss, ws) + } } + return !lastPage + }) + + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == s3.ErrCodeNoSuchBucket { + return nil, fmt.Errorf(errS3NoSuchBucket, err) } sort.Strings(wss[1:])