Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initiate work on PutObjectTagging ref PR#71 and issue #72 #75

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions awscli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,20 @@ func TestCLILsFiles(t *testing.T) {
t.Fatal()
}

cli.backendPutString(defaultBucket, "test-one", nil, "hello")
cli.backendPutString(defaultBucket, "test-one", nil, nil, "hello")
cli.assertLsFiles(defaultBucket, "",
nil, []string{"test-one"})

cli.backendPutString(defaultBucket, "test-two", nil, "hello")
cli.backendPutString(defaultBucket, "test-two", nil, nil, "hello")
cli.assertLsFiles(defaultBucket, "",
nil, []string{"test-one", "test-two"})

// only "test-one" and "test-two" should pass the prefix match
cli.backendPutString(defaultBucket, "no-match", nil, "hello")
cli.backendPutString(defaultBucket, "no-match", nil, nil, "hello")
cli.assertLsFiles(defaultBucket, "test-",
nil, []string{"test-one", "test-two"})

cli.backendPutString(defaultBucket, "test/yep", nil, "hello")
cli.backendPutString(defaultBucket, "test/yep", nil, nil, "hello")
cli.assertLsFiles(defaultBucket, "",
[]string{"test/"}, []string{"no-match", "test-one", "test-two"})

Expand All @@ -74,8 +74,8 @@ func TestCLIRmOne(t *testing.T) {
cli := newTestCLI(t)
defer cli.Close()

cli.backendPutString(defaultBucket, "foo", nil, "hello")
cli.backendPutString(defaultBucket, "bar", nil, "hello")
cli.backendPutString(defaultBucket, "foo", nil, nil, "hello")
cli.backendPutString(defaultBucket, "bar", nil, nil, "hello")
cli.assertLsFiles(defaultBucket, "", nil, []string{"foo", "bar"})

cli.rm(cli.fileArg(defaultBucket, "foo"))
Expand All @@ -86,9 +86,9 @@ func TestCLIRmMulti(t *testing.T) {
cli := newTestCLI(t)
defer cli.Close()

cli.backendPutString(defaultBucket, "foo", nil, "hello")
cli.backendPutString(defaultBucket, "bar", nil, "hello")
cli.backendPutString(defaultBucket, "baz", nil, "hello")
cli.backendPutString(defaultBucket, "foo", nil, nil, "hello")
cli.backendPutString(defaultBucket, "bar", nil, nil, "hello")
cli.backendPutString(defaultBucket, "baz", nil, nil, "hello")
cli.assertLsFiles(defaultBucket, "", nil, []string{"foo", "bar", "baz"})

cli.rmMulti(defaultBucket, "foo", "bar", "baz")
Expand Down Expand Up @@ -117,7 +117,7 @@ func TestCLIDownload(t *testing.T) {
cli := newTestCLI(t)
defer cli.Close()

cli.backendPutBytes(defaultBucket, "foo", nil, tc.in)
cli.backendPutBytes(defaultBucket, "foo", nil, nil, tc.in)
out := cli.download(defaultBucket, "foo")
if !bytes.Equal(out, tc.in) {
t.Fatal()
Expand Down
5 changes: 3 additions & 2 deletions backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
type Object struct {
Name string
Metadata map[string]string
Tags map[string]string
Size int64
Contents io.ReadCloser
Hash []byte
Expand Down Expand Up @@ -229,7 +230,7 @@ type Backend interface {
//
// The size can be used if the backend needs to read the whole reader; use
// gofakes3.ReadAll() for this job rather than ioutil.ReadAll().
PutObject(bucketName, key string, meta map[string]string, input io.Reader, size int64) (PutObjectResult, error)
PutObject(bucketName, key string, meta map[string]string, tags map[string]string, input io.Reader, size int64) (PutObjectResult, error)

DeleteMulti(bucketName string, objects ...string) (MultiDeleteResult, error)

Expand Down Expand Up @@ -339,7 +340,7 @@ func CopyObject(db Backend, srcBucket, srcKey, dstBucket, dstKey string, meta ma
}
defer c.Contents.Close()

_, err = db.PutObject(dstBucket, dstKey, meta, c.Contents, c.Size)
_, err = db.PutObject(dstBucket, dstKey, meta, c.Tags, c.Contents, c.Size)
if err != nil {
return
}
Expand Down
18 changes: 9 additions & 9 deletions backend/s3afero/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestPutGet(t *testing.T) {
}

contents := []byte("contents")
if _, err := backend.PutObject("test", "yep", meta, bytes.NewReader(contents), int64(len(contents))); err != nil {
if _, err := backend.PutObject("test", "yep", meta, nil, bytes.NewReader(contents), int64(len(contents))); err != nil {
t.Fatal(err)
}
hasher := md5.New()
Expand Down Expand Up @@ -89,7 +89,7 @@ func TestPutGetRange(t *testing.T) {

contents := []byte("contents")
expected := contents[1:7]
if _, err := backend.PutObject("test", "yep", meta, bytes.NewReader(contents), int64(len(contents))); err != nil {
if _, err := backend.PutObject("test", "yep", meta, nil, bytes.NewReader(contents), int64(len(contents))); err != nil {
t.Fatal(err)
}
hasher := md5.New()
Expand Down Expand Up @@ -134,12 +134,12 @@ func TestPutListRoot(t *testing.T) {
}

contents1 := []byte("contents1")
if _, err := backend.PutObject("test", "foo", meta, bytes.NewReader(contents1), int64(len(contents1))); err != nil {
if _, err := backend.PutObject("test", "foo", meta, nil, bytes.NewReader(contents1), int64(len(contents1))); err != nil {
t.Fatal(err)
}

contents2 := []byte("contents2")
if _, err := backend.PutObject("test", "bar", meta, bytes.NewReader(contents2), int64(len(contents2))); err != nil {
if _, err := backend.PutObject("test", "bar", meta, nil, bytes.NewReader(contents2), int64(len(contents2))); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -180,12 +180,12 @@ func TestPutListDir(t *testing.T) {
}

contents1 := []byte("contents1")
if _, err := backend.PutObject("test", "foo/bar", meta, bytes.NewReader(contents1), int64(len(contents1))); err != nil {
if _, err := backend.PutObject("test", "foo/bar", meta, nil, bytes.NewReader(contents1), int64(len(contents1))); err != nil {
t.Fatal(err)
}

contents2 := []byte("contents2")
if _, err := backend.PutObject("test", "foo/baz", meta, bytes.NewReader(contents2), int64(len(contents2))); err != nil {
if _, err := backend.PutObject("test", "foo/baz", meta, nil, bytes.NewReader(contents2), int64(len(contents2))); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -226,7 +226,7 @@ func TestPutDelete(t *testing.T) {
}

contents := []byte("contents1")
if _, err := backend.PutObject("test", "foo", meta, bytes.NewReader(contents), int64(len(contents))); err != nil {
if _, err := backend.PutObject("test", "foo", meta, nil, bytes.NewReader(contents), int64(len(contents))); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -258,12 +258,12 @@ func TestPutDeleteMulti(t *testing.T) {
}

contents1 := []byte("contents1")
if _, err := backend.PutObject("test", "foo/bar", meta, bytes.NewReader(contents1), int64(len(contents1))); err != nil {
if _, err := backend.PutObject("test", "foo/bar", meta, nil, bytes.NewReader(contents1), int64(len(contents1))); err != nil {
t.Fatal(err)
}

contents2 := []byte("contents2")
if _, err := backend.PutObject("test", "foo/baz", meta, bytes.NewReader(contents2), int64(len(contents2))); err != nil {
if _, err := backend.PutObject("test", "foo/baz", meta, nil, bytes.NewReader(contents2), int64(len(contents2))); err != nil {
t.Fatal(err)
}

Expand Down
1 change: 1 addition & 0 deletions backend/s3afero/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type Metadata struct {
File string
ModTime time.Time
Tags map[string]string
Size int64
Hash []byte
Meta map[string]string
Expand Down
5 changes: 5 additions & 0 deletions backend/s3afero/multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ func (db *MultiBucketBackend) HeadObject(bucketName, objectName string) (*gofake
Name: objectName,
Hash: meta.Hash,
Metadata: meta.Meta,
Tags: meta.Tags,
Size: size,
Contents: s3io.NoOpReadCloser{},
}, nil
Expand Down Expand Up @@ -380,6 +381,7 @@ func (db *MultiBucketBackend) GetObject(bucketName, objectName string, rangeRequ
Name: objectName,
Hash: meta.Hash,
Metadata: meta.Meta,
Tags: meta.Tags,
Range: rnge,
Size: size,
Contents: rdr,
Expand All @@ -389,9 +391,11 @@ func (db *MultiBucketBackend) GetObject(bucketName, objectName string, rangeRequ
func (db *MultiBucketBackend) PutObject(
bucketName, objectName string,
meta map[string]string,
tags map[string]string,
input io.Reader, size int64,
) (result gofakes3.PutObjectResult, err error) {

// merge metadata
err = gofakes3.MergeMetadata(db, bucketName, objectName, meta)
if err != nil {
return result, err
Expand Down Expand Up @@ -453,6 +457,7 @@ func (db *MultiBucketBackend) PutObject(
storedMeta := &Metadata{
File: objectPath,
Hash: hasher.Sum(nil),
Tags: tags,
Meta: meta,
Size: stat.Size(),
ModTime: stat.ModTime(),
Expand Down
4 changes: 4 additions & 0 deletions backend/s3afero/single.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ func (db *SingleBucketBackend) ensureMeta(
return &Metadata{
objectPath,
mtime,
nil,
size,
hash,
map[string]string{},
Expand Down Expand Up @@ -256,6 +257,7 @@ func (db *SingleBucketBackend) HeadObject(bucketName, objectName string) (*gofak
Name: objectName,
Hash: meta.Hash,
Metadata: meta.Meta,
Tags: meta.Tags,
Size: size,
Contents: s3io.NoOpReadCloser{},
}, nil
Expand Down Expand Up @@ -322,6 +324,7 @@ func (db *SingleBucketBackend) GetObject(bucketName, objectName string, rangeReq
func (db *SingleBucketBackend) PutObject(
bucketName, objectName string,
meta map[string]string,
tags map[string]string,
input io.Reader, size int64,
) (result gofakes3.PutObjectResult, err error) {

Expand Down Expand Up @@ -383,6 +386,7 @@ func (db *SingleBucketBackend) PutObject(
File: objectName,
Hash: hasher.Sum(nil),
Meta: meta,
Tags: tags,
Size: stat.Size(),
ModTime: stat.ModTime(),
}
Expand Down
2 changes: 2 additions & 0 deletions backend/s3bolt/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ func (db *Backend) GetObject(bucketName, objectName string, rangeRequest *gofake
func (db *Backend) PutObject(
bucketName, objectName string,
meta map[string]string,
tags map[string]string,
input io.Reader, size int64,
) (result gofakes3.PutObjectResult, err error) {

Expand All @@ -319,6 +320,7 @@ func (db *Backend) PutObject(
data, err := bson.Marshal(&boltObject{
Name: objectName,
Metadata: meta,
Tags: tags,
Size: int64(len(bts)),
LastModified: mod,
Contents: bts,
Expand Down
2 changes: 2 additions & 0 deletions backend/s3bolt/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type boltBucket struct {
type boltObject struct {
Name string
Metadata map[string]string
Tags map[string]string
LastModified time.Time
Size int64
Contents []byte
Expand All @@ -44,6 +45,7 @@ func (b *boltObject) Object(objectName string, rangeRequest *gofakes3.ObjectRang
return &gofakes3.Object{
Name: objectName,
Metadata: b.Metadata,
Tags: b.Tags,
Size: b.Size,
Contents: s3io.ReaderWithDummyCloser{Reader: bytes.NewReader(data)},
Range: rnge,
Expand Down
3 changes: 2 additions & 1 deletion backend/s3mem/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (db *Backend) GetObject(bucketName, objectName string, rangeRequest *gofake
return result, nil
}

func (db *Backend) PutObject(bucketName, objectName string, meta map[string]string, input io.Reader, size int64) (result gofakes3.PutObjectResult, err error) {
func (db *Backend) PutObject(bucketName, objectName string, meta map[string]string, tags map[string]string, input io.Reader, size int64) (result gofakes3.PutObjectResult, err error) {
// No need to lock the backend while we read the data into memory; it holds
// the write lock open unnecessarily, and could be blocked for an unreasonably
// long time by a connection timing out:
Expand Down Expand Up @@ -250,6 +250,7 @@ func (db *Backend) PutObject(bucketName, objectName string, meta map[string]stri
hash: hash[:],
etag: `"` + hex.EncodeToString(hash[:]) + `"`,
metadata: meta,
tags: tags,
lastModified: db.timeSource.Now(),
}

Expand Down
2 changes: 2 additions & 0 deletions backend/s3mem/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type bucketData struct {
hash []byte
etag string
metadata map[string]string
tags map[string]string
}

func (bi *bucketData) toObject(rangeRequest *gofakes3.ObjectRangeRequest, withBody bool) (obj *gofakes3.Object, err error) {
Expand Down Expand Up @@ -152,6 +153,7 @@ func (bi *bucketData) toObject(rangeRequest *gofakes3.ObjectRangeRequest, withBo
Name: bi.name,
Hash: bi.hash,
Metadata: bi.metadata,
Tags: bi.tags,
Size: sz,
Range: rnge,
IsDeleteMarker: bi.deleteMarker,
Expand Down
65 changes: 63 additions & 2 deletions gofakes3.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ func (g *GoFakeS3) createObjectBrowserUpload(bucket string, w http.ResponseWrite
return err
}

result, err := g.storage.PutObject(bucket, key, meta, rdr, fileHeader.Size)
result, err := g.storage.PutObject(bucket, key, meta, nil, rdr, fileHeader.Size)
if err != nil {
return err
}
Expand Down Expand Up @@ -674,7 +674,7 @@ func (g *GoFakeS3) createObject(bucket, object string, w http.ResponseWriter, r
return err
}

result, err := g.storage.PutObject(bucket, object, meta, rdr, size)
result, err := g.storage.PutObject(bucket, object, meta, nil, rdr, size)
if err != nil {
return err
}
Expand Down Expand Up @@ -907,6 +907,67 @@ func (g *GoFakeS3) putMultipartUploadPart(bucket, object string, uploadID Upload
return nil
}

// From the docs:
//
// Updating is usually done via different e.g., PutObject routes; but
// PutObjectTagging is one example where existing objects are updated in situ
//
// Sets the supplied tag-set to an object that already exists in a bucket.
//
// A tag is a key-value pair. You can associate tags with an object by sending a
// PUT request against the tagging subresource that is associated with the
// object.
func (g *GoFakeS3) updateObjectWithTags(bucket, object string, version string, w http.ResponseWriter, r *http.Request) error {
// write keys / metadata to object
if err := g.ensureBucketExists(bucket); err != nil {
return err
}

var in Tagging
if err := g.xmlDecodeBody(r.Body, &in); err != nil {
return err
}

rnge, err := parseRangeHeader(r.Header.Get("Range"))
if err != nil {
return err
}

obj, err := g.storage.GetObject(bucket, object, rnge)
if err != nil {
return err
}
if obj.Tags == nil {
obj.Tags = map[string]string{}
}
for _, v := range in.TagSet.Tag {
obj.Tags[v.Key] = v.Value
}

result, err := g.storage.PutObject(bucket, object, obj.Metadata, obj.Tags, obj.Contents, obj.Size)
if err != nil {
return err
}
if result.VersionID != "" {
w.Header().Set("x-amz-version-id", string(result.VersionID))
}

return nil
}

func (g *GoFakeS3) getObjectTags(bucket, object string, version string, w http.ResponseWriter, r *http.Request) error {
obj, err := g.storage.HeadObject(bucket, object)
if err != nil {
return err
}
out := Tagging{}
for k, v := range obj.Tags {
out.TagSet.Tag = append(out.TagSet.Tag, Tag{Key: k, Value: v})
}

return g.xmlEncoder(w).Encode(out)
}

func (g *GoFakeS3) abortMultipartUpload(bucket, object string, uploadID UploadID, w http.ResponseWriter, r *http.Request) error {
g.log.Print(LogInfo, "abort multipart upload", bucket, object, uploadID)
if err := g.uploader.AbortMultipartUpload(bucket, object, uploadID); err != nil {
Expand Down
Loading