driftctl/pkg/iac/terraform/state/backend/s3_reader.go

72 lines
1.5 KiB
Go
Raw Normal View History

package backend
import (
"fmt"
"io"
"strings"
"github.com/aws/aws-sdk-go/aws/session"
2021-02-09 18:43:39 +00:00
"github.com/pkg/errors"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3iface"
)
const backendS3 = "s3"
type S3Backend struct {
input s3.GetObjectInput
reader io.ReadCloser
S3Client s3iface.S3API
}
func NewS3Reader(path string) (*S3Backend, error) {
backend := S3Backend{}
bucketPath := strings.Split(path, "/")
if len(bucketPath) < 2 {
2021-02-09 18:43:39 +00:00
return nil, errors.New(fmt.Sprintf("Unable to parse S3 path: %s. Must be BUCKET_NAME/PATH/TO/OBJECT", path))
}
bucket := bucketPath[0]
key := strings.Join(bucketPath[1:], "/")
backend.input = s3.GetObjectInput{
Key: &key,
Bucket: &bucket,
}
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))
backend.S3Client = s3.New(sess)
return &backend, nil
}
func (s *S3Backend) Read(p []byte) (n int, err error) {
if s.reader == nil {
response, err := s.S3Client.GetObject(&s.input)
if err != nil {
requestFailure, ok := err.(s3.RequestFailure)
if ok {
2021-02-09 18:43:39 +00:00
return 0, errors.New(
fmt.Sprintf(
"Error reading state '%s' from s3 bucket '%s': %s",
*s.input.Key,
*s.input.Bucket,
requestFailure.Message(),
),
)
}
return 0, err
}
s.reader = response.Body
}
return s.reader.Read(p)
}
func (s *S3Backend) Close() error {
if s.reader != nil {
return s.reader.Close()
}
2021-02-09 18:43:39 +00:00
return errors.New("Unable to close reader as nothing was opened")
}