Skip to content

Commit

Permalink
enhance(filesystem/s3): presign enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed Feb 2, 2025
1 parent 4a6f0d2 commit c7dd794
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 24 deletions.
19 changes: 19 additions & 0 deletions pkg/filesystem/metadata_context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package filesystem

import (
"context"
"github.com/octohelm/courier/pkg/courier"
)

type metadataCtx struct{}

func MetadataFromContext(ctx context.Context) courier.Metadata {
if v, ok := ctx.Value(metadataCtx{}).(courier.Metadata); ok {
return v
}
return courier.Metadata{}
}

func MetadataInjectContext(ctx context.Context, meta courier.Metadata) context.Context {
return context.WithValue(ctx, metadataCtx{}, meta)
}
19 changes: 15 additions & 4 deletions pkg/filesystem/s3/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,21 @@ func (c *Config) AsFileSystem(ctx context.Context) (filesystem.FileSystem, error
}

f := &fs{
c: client,
bucket: c.Bucket(),
prefix: c.Prefix(),
presignAs: presignAs,
s3Client: client,
bucket: c.Bucket(),
prefix: c.Prefix(),
}

if presignAs != nil {
clientForPresign, err := minio.New(presignAs.Host, o)
if err != nil {
return nil, fmt.Errorf("new s3 client failed: %w", err)
}

presignAs.Host = c.Bucket() + "." + presignAs.Host

f.presignAs = presignAs
f.s3ClientForPresign = clientForPresign
}

c.fs = f
Expand Down
30 changes: 21 additions & 9 deletions pkg/filesystem/s3/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func openDir(ctx context.Context, fs *fs, name string) (filesystem.File, error)
}
}

_, err := fs.c.PutObject(ctx, fs.bucket, fs.path(path.Join(name, dirHolder)), bytes.NewBuffer(nil), 0, minio.PutObjectOptions{})
_, err := fs.s3Client.PutObject(ctx, fs.bucket, fs.path(path.Join(name, dirHolder)), bytes.NewBuffer(nil), 0, minio.PutObjectOptions{})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -67,6 +67,18 @@ func openFileForWrite(ctx context.Context, fs *fs, name string, flags int) (file
f.streamWriter = writer
f.streamWriterErrCh = make(chan error)

putOptions := minio.PutObjectOptions{}

metadata := filesystem.MetadataFromContext(ctx)

if v := metadata.Get("Content-Type"); v != "" {
putOptions.ContentType = v
}

if v := metadata.Get("Cache-Control"); v != "" {
putOptions.CacheControl = v
}

go func() {
var err error
defer func() {
Expand All @@ -76,21 +88,21 @@ func openFileForWrite(ctx context.Context, fs *fs, name string, flags int) (file
if flags&os.O_CREATE != 0 {
// when create new file
// to put 0x00 as placeholder
_, err := f.fs.c.PutObject(f.ctx, f.fs.bucket, f.fs.path(f.name), bytes.NewBuffer([]byte{0x00}), 1, minio.PutObjectOptions{})
_, err := f.fs.s3Client.PutObject(f.ctx, f.fs.bucket, f.fs.path(f.name), bytes.NewBuffer([]byte{0x00}), 1, putOptions)
if err != nil {
_ = writer.Close()
return
}
}

_, err = f.fs.c.PutObject(f.ctx, f.fs.bucket, f.fs.path(f.name), reader, -1, minio.PutObjectOptions{})
_, err = f.fs.s3Client.PutObject(f.ctx, f.fs.bucket, f.fs.path(f.name), reader, -1, putOptions)
if err != nil {
_ = writer.Close()
}
}()

if presignAs := fs.presignAs; presignAs != nil {
u, err := fs.c.PresignedPutObject(ctx, fs.bucket, fs.path(name), 5*time.Minute)
if presignAs, ok := fs.presignForWrite(); ok {
u, err := fs.presignClient().PresignedPutObject(ctx, fs.bucket, fs.path(name), 5*time.Minute)
if err != nil {
return nil, err
}
Expand All @@ -110,15 +122,15 @@ func openFileForWrite(ctx context.Context, fs *fs, name string, flags int) (file
func openFileForRead(ctx context.Context, fs *fs, name string) (filesystem.File, error) {
f := &file{ctx: ctx, fs: fs, name: name}

o, err := fs.c.GetObject(ctx, fs.bucket, fs.path(name), minio.GetObjectOptions{})
o, err := fs.s3Client.GetObject(ctx, fs.bucket, fs.path(name), minio.GetObjectOptions{})
if err != nil {
return nil, err
}

f.object = o

if presignAs := fs.presignAs; presignAs != nil {
u, err := fs.c.PresignedGetObject(ctx, fs.bucket, fs.path(name), 5*time.Minute, nil)
if presignAs, ok := fs.presignForRead(); ok {
u, err := fs.presignClient().PresignedGetObject(ctx, fs.bucket, fs.path(name), 5*time.Minute, nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -177,7 +189,7 @@ func (f *file) Readdir(n int) ([]os.FileInfo, error) {
name += "/"
}

objCh := f.fs.c.ListObjects(context.Background(), f.fs.bucket, minio.ListObjectsOptions{
objCh := f.fs.s3Client.ListObjects(context.Background(), f.fs.bucket, minio.ListObjectsOptions{
Prefix: name,
})

Expand Down
51 changes: 42 additions & 9 deletions pkg/filesystem/s3/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import (
)

type fs struct {
c *minio.Client
presignAs *url.URL
bucket string
prefix string
s3Client *minio.Client
s3ClientForPresign *minio.Client
presignAs *url.URL

bucket string
prefix string
}

func (fsys *fs) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
Expand Down Expand Up @@ -112,7 +114,7 @@ func (fsys *fs) Rename(ctx context.Context, oldName, newName string) error {
return fsys.forceRemove(ctx, oldName, true)
}

_, err = fsys.c.CopyObject(
_, err = fsys.s3Client.CopyObject(
ctx,
minio.CopyDestOptions{
Bucket: fsys.bucket,
Expand Down Expand Up @@ -169,14 +171,14 @@ func (fsys *fs) RemoveAll(ctx context.Context, name string) error {

func (fsys *fs) forceRemove(ctx context.Context, name string, isDir bool) error {
if isDir {
if err := fsys.c.RemoveObject(ctx, fsys.bucket, fsys.path(filepath.Join(name, dirHolder)), minio.RemoveObjectOptions{
if err := fsys.s3Client.RemoveObject(ctx, fsys.bucket, fsys.path(filepath.Join(name, dirHolder)), minio.RemoveObjectOptions{
ForceDelete: true,
}); err != nil {
return err
}
}

return fsys.c.RemoveObject(ctx, fsys.bucket, fsys.path(name), minio.RemoveObjectOptions{
return fsys.s3Client.RemoveObject(ctx, fsys.bucket, fsys.path(name), minio.RemoveObjectOptions{
ForceDelete: true,
})
}
Expand All @@ -193,7 +195,7 @@ func (fsys *fs) Stat(ctx context.Context, name string) (os.FileInfo, error) {
return fsutil.NewDirFileInfo(name), nil
}

info, err := fsys.c.StatObject(ctx, fsys.bucket, fsys.path(name), minio.StatObjectOptions{})
info, err := fsys.s3Client.StatObject(ctx, fsys.bucket, fsys.path(name), minio.StatObjectOptions{})
if err != nil {
var errorResponse minio.ErrorResponse
if errors.As(err, &errorResponse) {
Expand All @@ -219,7 +221,7 @@ func (fsys *fs) Stat(ctx context.Context, name string) (os.FileInfo, error) {
func (fsys *fs) statDirectory(ctx context.Context, name string) (os.FileInfo, error) {
nameClean := path.Clean(name)

objects := fsys.c.ListObjects(ctx, fsys.bucket, minio.ListObjectsOptions{
objects := fsys.s3Client.ListObjects(ctx, fsys.bucket, minio.ListObjectsOptions{
Prefix: fsys.path(nameClean),
MaxKeys: 1,
})
Expand All @@ -234,3 +236,34 @@ func (fsys *fs) statDirectory(ctx context.Context, name string) (os.FileInfo, er
Err: os.ErrNotExist,
}
}

func (fsys *fs) presignClient() *minio.Client {
if presignAs := fsys.presignAs; presignAs != nil {

if presignAs.User != nil {
if pwd, ok := presignAs.User.Password(); ok && pwd == "fake" {
return fsys.s3Client
}
}
return fsys.s3ClientForPresign
}

return fsys.s3Client
}

func (fsys *fs) presignForWrite() (*url.URL, bool) {
if fsys.presignAs != nil {
if fsys.presignAs.User != nil && fsys.presignAs.User.Username() == "rw" {
return fsys.presignAs, true
}
}

return nil, false
}

func (fsys *fs) presignForRead() (*url.URL, bool) {
if fsys.presignAs != nil {
return fsys.presignAs, true
}
return nil, false
}
4 changes: 2 additions & 2 deletions pkg/filesystem/s3/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestS3Fs(t *testing.T) {
}

func TestS3WithPresignAs(t *testing.T) {
fsys := newFakeS3FS(t, forPresign("https://x.io"))
fsys := newFakeS3FS(t, forPresign("https://rw:fake@x.io"))
err := fsys.Mkdir(context.Background(), "/x", os.ModePerm|os.ModeDir)
testingx.Expect(t, err, testingx.BeNil[error]())

Expand All @@ -46,7 +46,7 @@ func TestS3WithPresignAs(t *testing.T) {
testingx.Expect(t, err, testingx.BeNil[error]())
defer f.Close()

testingx.Expect(t, f.(courierhttp.RedirectDescriber).Location().Host, testingx.Be("x.io"))
testingx.Expect(t, f.(courierhttp.RedirectDescriber).Location().Host, testingx.Be("test.x.io"))
}

func forPresign(endpoint string) func(c *Config) {
Expand Down

0 comments on commit c7dd794

Please sign in to comment.