featurebase/idk/internal/s3.go
CLoZengineer f9ddb5d5c1
fix: updating code to meet linting requirements (#2171)
* removes unused filesize function

* removes ioutil usage

* updates ioutil.ReadAll to io.ReadAll

* updates ioutil.TempFile to os.CreateTemp

* updates ioutil.TempDir to os.MkdirTemp

* updates ioutil.ReadAll to os.ReadAll

* update ioutil.WriteFile to os.WriteFile

* updates ioutil.Discard to io.Discard

* updates ioutil.ReadDir to os.ReadDir where applicable

* removes unused code in idk

* creates type to use for context value keys

* replaces assert.Nil with assert.NoError for error checks
2022-09-29 12:34:29 -04:00

99 lines
2.5 KiB
Go

package internal
import (
"bytes"
"net/url"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3iface"
"github.com/pkg/errors"
)
var FileOrURLNotFound = errors.New("file or url does not exist")
// ReadFileOrURL reads a path from the filesystem or an s3 URL.
// The s3client parameter is required if reading an s3 URL.
// ReadFileOrURL returns FileOrURLNotFound when the local filesystem
// path or remote s3 location is not found.
func ReadFileOrURL(name string, s3client s3iface.S3API) ([]byte, error) {
var content []byte
var err error
if strings.HasPrefix(name, "s3://") {
if s3client == nil {
return nil, errors.New("missing s3 client")
}
u, err := url.Parse(name)
if err != nil {
return nil, errors.Wrapf(err, "parsing S3 URL %v", name)
}
bucket := u.Host
key := u.Path[1:] // strip leading slash
result, err := s3client.GetObject(&s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
})
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeNoSuchBucket:
return nil, FileOrURLNotFound
case s3.ErrCodeNoSuchKey:
return nil, FileOrURLNotFound
}
}
return nil, errors.Wrapf(err, "fetching S3 object %v", name)
}
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(result.Body)
if err != nil {
return nil, err
}
content = buf.Bytes()
} else {
content, err = os.ReadFile(name)
if err != nil {
if os.IsNotExist(err) {
return nil, FileOrURLNotFound
}
return nil, errors.Wrapf(err, "reading file %v", name)
}
}
return content, nil
}
func WriteFileOrURL(name string, contents []byte, s3client s3iface.S3API) error {
var err error
if strings.HasPrefix(name, "s3://") {
if s3client == nil {
return errors.New("missing s3 client")
}
u, err := url.Parse(name)
if err != nil {
return errors.Wrapf(err, "parsing S3 URL %v", name)
}
bucket := u.Host
key := u.Path[1:] // strip leading slash
_, err = s3client.PutObject(&s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: bytes.NewReader(contents),
ContentLength: aws.Int64(int64(len(contents))),
})
if err != nil {
return errors.Wrapf(err, "putting S3 object %v", name)
}
} else {
err = os.WriteFile(name, contents, 0644)
if err != nil {
return errors.Wrapf(err, "reading file %v", name)
}
}
return nil
}