From de8dd2692da40e3bceee26b421c84cf8585158a2 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 27 Apr 2022 17:59:47 -0300 Subject: [PATCH 01/36] Create prefixed bucket Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 10 ++++- pkg/objstore/prefixed_bucket.go | 77 +++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 pkg/objstore/prefixed_bucket.go diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index f066bde362..ef4874c308 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -40,7 +40,11 @@ const ( type BucketConfig struct { Type ObjProvider `yaml:"type"` - Config interface{} `yaml:"config"` + Config Config `yaml:"config"` +} + +type Config struct { + Prefix string `yaml:"prefix" default:""` } // NewBucket initializes and returns new object storage clients. @@ -81,5 +85,7 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } - return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), bucket, reg)), nil + + prefixedBucket := objstore.NewPrefixedBucket(bucket, bucketConf.Config.Prefix) + return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), prefixedBucket, reg)), nil } diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go new file mode 100644 index 0000000000..1fcaece37c --- /dev/null +++ b/pkg/objstore/prefixed_bucket.go @@ -0,0 +1,77 @@ +package objstore + +import ( + "context" + "io" +) + +type PrefixedBucket struct { + bkt Bucket + prefix string +} + +func NewPrefixedBucket(bkt Bucket, prefix string) Bucket { + pbkt := &PrefixedBucket{bkt: bkt, prefix: prefix} + return pbkt +} + +func withPrefix(prefix, name string) string { + return prefix + "/" + name +} + +func (p *PrefixedBucket) Close() error { + return p.bkt.Close() +} + +// Iter calls f for each entry in the given directory (not recursive.). The argument to f is the full +// object name including the prefix of the inspected directory. +// Entries are passed to function in sorted order. +func (p *PrefixedBucket) Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error { + return p.bkt.Iter(ctx, withPrefix(p.prefix, dir), f, options...) +} + +// Get returns a reader for the given object name. +func (p *PrefixedBucket) Get(ctx context.Context, name string) (io.ReadCloser, error) { + return p.bkt.Get(ctx, withPrefix(p.prefix, name)) +} + +// GetRange returns a new range reader for the given object name and range. +func (p *PrefixedBucket) GetRange(ctx context.Context, name string, off int64, length int64) (io.ReadCloser, error) { + return p.bkt.GetRange(ctx, withPrefix(p.prefix, name), off, length) +} + +// Exists checks if the given object exists in the bucket. +func (p *PrefixedBucket) Exists(ctx context.Context, name string) (bool, error) { + return p.bkt.Exists(ctx, withPrefix(p.prefix, name)) +} + +// IsObjNotFoundErr returns true if error means that object is not found. Relevant to Get operations. +func (p *PrefixedBucket) IsObjNotFoundErr(err error) bool { + return p.bkt.IsObjNotFoundErr(err) +} + +// Attributes returns information about the specified object. +func (p PrefixedBucket) Attributes(ctx context.Context, name string) (ObjectAttributes, error) { + return p.bkt.Attributes(ctx, withPrefix(p.prefix, name)) +} + +// func (p *PrefixedBucket) Attributes(ctx context.Context, name string) (ObjectAttributes, error) { +// return p.bkt.Attributes(ctx, withPrefix(p.prefix, name)) +// } + +// Upload the contents of the reader as an object into the bucket. +// Upload should be idempotent. +func (p *PrefixedBucket) Upload(ctx context.Context, name string, r io.Reader) error { + return p.bkt.Upload(ctx, withPrefix(p.prefix, name), r) +} + +// Delete removes the object with the given name. +// If object does not exists in the moment of deletion, Delete should throw error. +func (p *PrefixedBucket) Delete(ctx context.Context, name string) error { + return p.bkt.Delete(ctx, withPrefix(p.prefix, name)) +} + +// Name returns the bucket name for the provider. +func (p *PrefixedBucket) Name() string { + return p.bkt.Name() +} From 64642db3d1d8b0794bd915abf403eeb35dd66ae6 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Fri, 29 Apr 2022 07:57:01 -0300 Subject: [PATCH 02/36] started PrefixedBucket tests Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/prefixed_bucket.go | 15 +++++++++++---- pkg/objstore/prefixed_bucket_test.go | 8 ++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 pkg/objstore/prefixed_bucket_test.go diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 1fcaece37c..2c0b23d8d7 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -15,6 +15,13 @@ func NewPrefixedBucket(bkt Bucket, prefix string) Bucket { return pbkt } +func conditionalPrefix(prefix, name string) string { + if len(name) > 0 && len(prefix) > 0 { + return prefix + "/" + name + } + return name +} + func withPrefix(prefix, name string) string { return prefix + "/" + name } @@ -27,17 +34,17 @@ func (p *PrefixedBucket) Close() error { // object name including the prefix of the inspected directory. // Entries are passed to function in sorted order. func (p *PrefixedBucket) Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error { - return p.bkt.Iter(ctx, withPrefix(p.prefix, dir), f, options...) + return p.bkt.Iter(ctx, conditionalPrefix(p.prefix, dir), f, options...) } // Get returns a reader for the given object name. func (p *PrefixedBucket) Get(ctx context.Context, name string) (io.ReadCloser, error) { - return p.bkt.Get(ctx, withPrefix(p.prefix, name)) + return p.bkt.Get(ctx, conditionalPrefix(p.prefix, name)) } // GetRange returns a new range reader for the given object name and range. func (p *PrefixedBucket) GetRange(ctx context.Context, name string, off int64, length int64) (io.ReadCloser, error) { - return p.bkt.GetRange(ctx, withPrefix(p.prefix, name), off, length) + return p.bkt.GetRange(ctx, conditionalPrefix(p.prefix, name), off, length) } // Exists checks if the given object exists in the bucket. @@ -52,7 +59,7 @@ func (p *PrefixedBucket) IsObjNotFoundErr(err error) bool { // Attributes returns information about the specified object. func (p PrefixedBucket) Attributes(ctx context.Context, name string) (ObjectAttributes, error) { - return p.bkt.Attributes(ctx, withPrefix(p.prefix, name)) + return p.bkt.Attributes(ctx, conditionalPrefix(p.prefix, name)) } // func (p *PrefixedBucket) Attributes(ctx context.Context, name string) (ObjectAttributes, error) { diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go new file mode 100644 index 0000000000..fdba9c4583 --- /dev/null +++ b/pkg/objstore/prefixed_bucket_test.go @@ -0,0 +1,8 @@ +package objstore + +import "testing" + +func TestPrefixedBucket_AcceptanceTest(t *testing.T) { + bkt := NewPrefixedBucket(NewInMemBucket(), "someprefix/anotherprefix") + AcceptanceTest(t, bkt) +} From 8e3e10263fda7cff39cc40ac4b75b2b93b431766 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Mon, 2 May 2022 14:01:15 -0300 Subject: [PATCH 03/36] finish objstore tests Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/prefixed_bucket.go | 32 ++++++++++++++++++++-------- pkg/objstore/prefixed_bucket_test.go | 2 +- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 2c0b23d8d7..667069d87c 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -3,6 +3,7 @@ package objstore import ( "context" "io" + "strings" ) type PrefixedBucket struct { @@ -11,10 +12,21 @@ type PrefixedBucket struct { } func NewPrefixedBucket(bkt Bucket, prefix string) Bucket { - pbkt := &PrefixedBucket{bkt: bkt, prefix: prefix} + pbkt := &PrefixedBucket{bkt: bkt, prefix: PrefixFormater(prefix)} return pbkt } +func PrefixFormater(prefix string) string { + formatedPrefix := prefix + if prefix[len(prefix)-1:] == "/" { + formatedPrefix = prefix[0 : len(prefix)-1] + } + if prefix[0:1] == "/" { + formatedPrefix = formatedPrefix[1:] + } + return formatedPrefix +} + func conditionalPrefix(prefix, name string) string { if len(name) > 0 && len(prefix) > 0 { return prefix + "/" + name @@ -34,7 +46,13 @@ func (p *PrefixedBucket) Close() error { // object name including the prefix of the inspected directory. // Entries are passed to function in sorted order. func (p *PrefixedBucket) Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error { - return p.bkt.Iter(ctx, conditionalPrefix(p.prefix, dir), f, options...) + pdir := withPrefix(p.prefix, dir) + if len(p.prefix) > 0 { + return p.bkt.Iter(ctx, pdir, func(s string) error { + return f(strings.Join(strings.Split(s, p.prefix+"/")[1:], "/")) + }, options...) + } + return p.bkt.Iter(ctx, pdir, f) } // Get returns a reader for the given object name. @@ -49,7 +67,7 @@ func (p *PrefixedBucket) GetRange(ctx context.Context, name string, off int64, l // Exists checks if the given object exists in the bucket. func (p *PrefixedBucket) Exists(ctx context.Context, name string) (bool, error) { - return p.bkt.Exists(ctx, withPrefix(p.prefix, name)) + return p.bkt.Exists(ctx, conditionalPrefix(p.prefix, name)) } // IsObjNotFoundErr returns true if error means that object is not found. Relevant to Get operations. @@ -62,20 +80,16 @@ func (p PrefixedBucket) Attributes(ctx context.Context, name string) (ObjectAttr return p.bkt.Attributes(ctx, conditionalPrefix(p.prefix, name)) } -// func (p *PrefixedBucket) Attributes(ctx context.Context, name string) (ObjectAttributes, error) { -// return p.bkt.Attributes(ctx, withPrefix(p.prefix, name)) -// } - // Upload the contents of the reader as an object into the bucket. // Upload should be idempotent. func (p *PrefixedBucket) Upload(ctx context.Context, name string, r io.Reader) error { - return p.bkt.Upload(ctx, withPrefix(p.prefix, name), r) + return p.bkt.Upload(ctx, conditionalPrefix(p.prefix, name), r) } // Delete removes the object with the given name. // If object does not exists in the moment of deletion, Delete should throw error. func (p *PrefixedBucket) Delete(ctx context.Context, name string) error { - return p.bkt.Delete(ctx, withPrefix(p.prefix, name)) + return p.bkt.Delete(ctx, conditionalPrefix(p.prefix, name)) } // Name returns the bucket name for the provider. diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index fdba9c4583..535b950437 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -3,6 +3,6 @@ package objstore import "testing" func TestPrefixedBucket_AcceptanceTest(t *testing.T) { - bkt := NewPrefixedBucket(NewInMemBucket(), "someprefix/anotherprefix") + bkt := NewPrefixedBucket(NewInMemBucket(), "/someprefix/anotherprefix/") AcceptanceTest(t, bkt) } From 124bc439f3873b0f5825de4744463401d12db041 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 4 May 2022 09:42:46 -0300 Subject: [PATCH 04/36] Simplify string removal logic Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 667069d87c..7596a9c7d2 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -12,21 +12,10 @@ type PrefixedBucket struct { } func NewPrefixedBucket(bkt Bucket, prefix string) Bucket { - pbkt := &PrefixedBucket{bkt: bkt, prefix: PrefixFormater(prefix)} + pbkt := &PrefixedBucket{bkt: bkt, prefix: strings.Trim(prefix, "/")} return pbkt } -func PrefixFormater(prefix string) string { - formatedPrefix := prefix - if prefix[len(prefix)-1:] == "/" { - formatedPrefix = prefix[0 : len(prefix)-1] - } - if prefix[0:1] == "/" { - formatedPrefix = formatedPrefix[1:] - } - return formatedPrefix -} - func conditionalPrefix(prefix, name string) string { if len(name) > 0 && len(prefix) > 0 { return prefix + "/" + name From 0e55117ee88f4a1a0492952e74311dc983e215f3 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 4 May 2022 09:43:07 -0300 Subject: [PATCH 05/36] Test more prefix cases on PrefixedBucket Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index 535b950437..34b5d06a29 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -5,4 +5,16 @@ import "testing" func TestPrefixedBucket_AcceptanceTest(t *testing.T) { bkt := NewPrefixedBucket(NewInMemBucket(), "/someprefix/anotherprefix/") AcceptanceTest(t, bkt) + + bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix/anotherprefix/") + AcceptanceTest(t, bkt) + + bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix/anotherprefix") + AcceptanceTest(t, bkt) + + bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix/") + AcceptanceTest(t, bkt) + + bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix") + AcceptanceTest(t, bkt) } From fffb2ef23461f69c9a6502bb8deb1e376da27acc Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 4 May 2022 09:51:32 -0300 Subject: [PATCH 06/36] Only use a prefixedbucket if we have a valid prefix Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index ef4874c308..dece31ce99 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -86,6 +86,17 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } - prefixedBucket := objstore.NewPrefixedBucket(bucket, bucketConf.Config.Prefix) + var prefixedBucket objstore.Bucket + if ValidPrefix(bucketConf.Config.Prefix) { + prefixedBucket = objstore.NewPrefixedBucket(bucket, bucketConf.Config.Prefix) + } else { + prefixedBucket = bucket + } + return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), prefixedBucket, reg)), nil } + +func ValidPrefix(prefix string) bool { + prefix = strings.Replace(prefix, "/", "", -1) + return len(prefix) > 0 +} From eec27500482a023aa13236b05068bd0070144f56 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 4 May 2022 15:05:10 -0300 Subject: [PATCH 07/36] Add single unit test for prefixedBucket prefix Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket_test.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index 34b5d06a29..45d0416c90 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -1,8 +1,15 @@ package objstore -import "testing" +import ( + "context" + "io/ioutil" + "strings" + "testing" -func TestPrefixedBucket_AcceptanceTest(t *testing.T) { + "github.com/thanos-io/thanos/pkg/testutil" +) + +func TestPrefixedBucket_Acceptance(t *testing.T) { bkt := NewPrefixedBucket(NewInMemBucket(), "/someprefix/anotherprefix/") AcceptanceTest(t, bkt) @@ -18,3 +25,17 @@ func TestPrefixedBucket_AcceptanceTest(t *testing.T) { bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix") AcceptanceTest(t, bkt) } + +func TestPrefixedBucket_UsesPrefix(t *testing.T) { + bkt := NewInMemBucket() + bkt.Upload(context.Background(), "our_prefix/file1.jpg", strings.NewReader("@test-data1")) + + pBkt := NewPrefixedBucket(bkt, "our_prefix") + rc1, err := pBkt.Get(context.Background(), "file1.jpg") + + testutil.Ok(t, err) + defer func() { testutil.Ok(t, rc1.Close()) }() + content, err := ioutil.ReadAll(rc1) + testutil.Ok(t, err) + testutil.Equals(t, "@test-data1", string(content)) +} From d4a209f3262ed47d4ca6b9a4134e4eab66d9bf76 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Wed, 4 May 2022 15:37:35 -0300 Subject: [PATCH 08/36] test other prefixes on UsesPrefixTest Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/prefixed_bucket_test.go | 33 ++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index 45d0416c90..aaf55c9251 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -10,27 +10,36 @@ import ( ) func TestPrefixedBucket_Acceptance(t *testing.T) { - bkt := NewPrefixedBucket(NewInMemBucket(), "/someprefix/anotherprefix/") + prefix := "/someprefix/anotherprefix/" + bkt := NewPrefixedBucket(NewInMemBucket(), prefix) AcceptanceTest(t, bkt) + UsesPrefixTest(t, bkt, prefix) - bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix/anotherprefix/") + prefix = "someprefix/anotherprefix/" + bkt = NewPrefixedBucket(NewInMemBucket(), prefix) AcceptanceTest(t, bkt) + UsesPrefixTest(t, bkt, prefix) - bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix/anotherprefix") + prefix = "someprefix/anotherprefix" + bkt = NewPrefixedBucket(NewInMemBucket(), prefix) AcceptanceTest(t, bkt) + UsesPrefixTest(t, bkt, prefix) - bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix/") + prefix = "someprefix/" + bkt = NewPrefixedBucket(NewInMemBucket(), prefix) AcceptanceTest(t, bkt) + UsesPrefixTest(t, bkt, prefix) - bkt = NewPrefixedBucket(NewInMemBucket(), "someprefix") + prefix = "someprefix" + bkt = NewPrefixedBucket(NewInMemBucket(), prefix) AcceptanceTest(t, bkt) + UsesPrefixTest(t, bkt, prefix) } -func TestPrefixedBucket_UsesPrefix(t *testing.T) { - bkt := NewInMemBucket() - bkt.Upload(context.Background(), "our_prefix/file1.jpg", strings.NewReader("@test-data1")) +func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { + bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/file1.jpg", strings.NewReader("@test-data1")) - pBkt := NewPrefixedBucket(bkt, "our_prefix") + pBkt := NewPrefixedBucket(bkt, prefix) rc1, err := pBkt.Get(context.Background(), "file1.jpg") testutil.Ok(t, err) @@ -38,4 +47,10 @@ func TestPrefixedBucket_UsesPrefix(t *testing.T) { content, err := ioutil.ReadAll(rc1) testutil.Ok(t, err) testutil.Equals(t, "@test-data1", string(content)) + + // Upload + // Delete + // GetRange + // Exists + // IsObjNotFoundErr } From d494c9e5d2ce1137aec49282846c5130fe415bbc Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Thu, 5 May 2022 17:33:00 -0300 Subject: [PATCH 09/36] add remaining methods to UsesPrefixTest Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/prefixed_bucket_test.go | 34 ++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index aaf55c9251..4c7522bad5 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -48,9 +48,33 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Ok(t, err) testutil.Equals(t, "@test-data1", string(content)) - // Upload - // Delete - // GetRange - // Exists - // IsObjNotFoundErr + pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("@test-data2")) + rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/") + "/file2.jpg") + + testutil.Ok(t, err) + defer func() { testutil.Ok(t, rc2.Close()) }() + contentUpload, err := ioutil.ReadAll(rc2) + testutil.Ok(t, err) + testutil.Equals(t, "@test-data2", string(contentUpload)) + + pBkt.Delete(context.Background(), "file2.jpg") + _, err = bkt.Get(context.Background(), strings.Trim(prefix, "/") + "/file2.jpg") + + testutil.NotOk(t, err) + testutil.Assert(t, pBkt.IsObjNotFoundErr(err), "expected not found error got %s", err) + + rc3, err := pBkt.GetRange(context.Background(), "file1.jpg", 1, 3) + testutil.Ok(t, err) + defer func() { testutil.Ok(t, rc3.Close()) }() + content, err = ioutil.ReadAll(rc3) + testutil.Ok(t, err) + testutil.Equals(t, "tes", string(content)) + + ok, err := pBkt.Exists(context.Background(), "file1.jpg") + testutil.Ok(t, err) + testutil.Assert(t, ok, "expected exits") + + attrs, err := pBkt.Attributes(context.Background(), "file1.jpg") + testutil.Ok(t, err) + testutil.Assert(t, attrs.Size == 11, "expected size to be equal to 11") } From 4161825eac9aa61e64b1ff472d43501b619ca38c Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Thu, 5 May 2022 17:33:51 -0300 Subject: [PATCH 10/36] add prefix to docs examples Signed-off-by: Maria Eduarda Duarte --- docs/storage.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/storage.md b/docs/storage.md index 7e10f5c98c..f416e2c7ce 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -64,6 +64,7 @@ type: S3 config: bucket: "" endpoint: "" + prefix: "" region: "" aws_sdk_auth: false access_key: "" @@ -330,6 +331,7 @@ config: storage_account_key: "" container: "" endpoint: "" + prefix: "" max_retries: 0 msi_resource: "" user_assigned_id: "" @@ -384,6 +386,7 @@ config: password: "" domain_id: "" domain_name: "" + prefix: "" project_id: "" project_name: "" project_domain_id: "" @@ -411,6 +414,7 @@ config: region: "" app_id: "" endpoint: "" + prefix: "" secret_key: "" secret_id: "" http_config: @@ -442,6 +446,7 @@ config: bucket: "" access_key_id: "" access_key_secret: "" + prefix: "" ``` Use --objstore.config-file to reference to this configuration file. @@ -457,6 +462,7 @@ config: endpoint: "" access_key: "" secret_key: "" + prefix: "" ``` #### Filesystem @@ -469,6 +475,7 @@ NOTE: This storage type is experimental and might be inefficient. It is NOT advi type: FILESYSTEM config: directory: "" + prefix: "" ``` ### How to add a new client to Thanos? From e6a9fb5a5b70cdb514e5d6633209a52d4bd4d7f0 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Fri, 6 May 2022 14:46:39 -0300 Subject: [PATCH 11/36] Simplify Iter method Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 7596a9c7d2..adaf8da2b5 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -35,13 +35,14 @@ func (p *PrefixedBucket) Close() error { // object name including the prefix of the inspected directory. // Entries are passed to function in sorted order. func (p *PrefixedBucket) Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error { - pdir := withPrefix(p.prefix, dir) if len(p.prefix) > 0 { + pdir := withPrefix(p.prefix, dir) + return p.bkt.Iter(ctx, pdir, func(s string) error { - return f(strings.Join(strings.Split(s, p.prefix+"/")[1:], "/")) + return f(strings.TrimPrefix(s, p.prefix+"/")) }, options...) } - return p.bkt.Iter(ctx, pdir, f) + return p.bkt.Iter(ctx, dir, f, options...) } // Get returns a reader for the given object name. From e7ae910cd615f8a183258bac696e31941dcc0dac Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Fri, 6 May 2022 15:16:42 -0300 Subject: [PATCH 12/36] add prefix explanation to S3 docs Signed-off-by: Maria Eduarda Duarte --- docs/storage.md | 2 ++ pkg/objstore/prefixed_bucket_test.go | 26 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/storage.md b/docs/storage.md index f416e2c7ce..16d1414ecb 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -103,6 +103,8 @@ At a minimum, you will need to provide a value for the `bucket`, `endpoint`, `ac However if you set `aws_sdk_auth: true` Thanos will use the default authentication methods of the AWS SDK for go based on [known environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) (`AWS_PROFILE`, `AWS_WEB_IDENTITY_TOKEN_FILE` ... etc) and known AWS config files (~/.aws/config). If you turn this on, then the `bucket` and `endpoint` are the required config keys. +The field `prefix` can be used to transparently use bucket prefixes in your S3 bucket. That way, you may point distinct Thanos instances to the same bucket, while avoiding one instance messing with the data from another instance. This will allow multiple Thanos deployments to use the same bucket without + The AWS region to endpoint mapping can be found in this [link](https://docs.aws.amazon.com/general/latest/gr/s3.html). Make sure you use a correct signature version. Currently AWS requires signature v4, so it needs `signature_version2: false`. If you don't specify it, you will get an `Access Denied` error. On the other hand, several S3 compatible APIs use `signature_version2: true`. diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index 4c7522bad5..64792f5524 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -3,6 +3,7 @@ package objstore import ( "context" "io/ioutil" + "sort" "strings" "testing" @@ -49,7 +50,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Equals(t, "@test-data1", string(content)) pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("@test-data2")) - rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/") + "/file2.jpg") + rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") testutil.Ok(t, err) defer func() { testutil.Ok(t, rc2.Close()) }() @@ -58,7 +59,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Equals(t, "@test-data2", string(contentUpload)) pBkt.Delete(context.Background(), "file2.jpg") - _, err = bkt.Get(context.Background(), strings.Trim(prefix, "/") + "/file2.jpg") + _, err = bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") testutil.NotOk(t, err) testutil.Assert(t, pBkt.IsObjNotFoundErr(err), "expected not found error got %s", err) @@ -77,4 +78,25 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { attrs, err := pBkt.Attributes(context.Background(), "file1.jpg") testutil.Ok(t, err) testutil.Assert(t, attrs.Size == 11, "expected size to be equal to 11") + + bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/dir/file1.jpg", strings.NewReader("@test-data1")) + seen := []string{} + testutil.Ok(t, pBkt.Iter(context.Background(), "", func(fn string) error { + seen = append(seen, fn) + return nil + }, WithRecursiveIter)) + expected := []string{"dir/file1.jpg", "file1.jpg"} + sort.Strings(expected) + sort.Strings(seen) + testutil.Equals(t, expected, seen) + + seen = []string{} + testutil.Ok(t, pBkt.Iter(context.Background(), "", func(fn string) error { + seen = append(seen, fn) + return nil + })) + expected = []string{"dir/", "file1.jpg"} + sort.Strings(expected) + sort.Strings(seen) + testutil.Equals(t, expected, seen) } From 6645a126d089c48d0d179a6cccd4e0dc8273213b Mon Sep 17 00:00:00 2001 From: jademcosta Date: Fri, 6 May 2022 15:30:34 -0300 Subject: [PATCH 13/36] Conclusion of prefix sentence on docs Signed-off-by: jademcosta --- docs/storage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/storage.md b/docs/storage.md index 16d1414ecb..6da3c94f3d 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -103,7 +103,7 @@ At a minimum, you will need to provide a value for the `bucket`, `endpoint`, `ac However if you set `aws_sdk_auth: true` Thanos will use the default authentication methods of the AWS SDK for go based on [known environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) (`AWS_PROFILE`, `AWS_WEB_IDENTITY_TOKEN_FILE` ... etc) and known AWS config files (~/.aws/config). If you turn this on, then the `bucket` and `endpoint` are the required config keys. -The field `prefix` can be used to transparently use bucket prefixes in your S3 bucket. That way, you may point distinct Thanos instances to the same bucket, while avoiding one instance messing with the data from another instance. This will allow multiple Thanos deployments to use the same bucket without +The field `prefix` can be used to transparently use prefixes in your S3 bucket. That way, you may point distinct Thanos instances to the same bucket, while avoiding one instance messing with the data from another instance. This allows multiple Thanos deployments to use the same bucket without having to list all the files in it when you point Thanos store to the bucket (even when you are using tenants feature). The AWS region to endpoint mapping can be found in this [link](https://docs.aws.amazon.com/general/latest/gr/s3.html). From cba5d77568b9f489f0469bc123cc6f444551ad1e Mon Sep 17 00:00:00 2001 From: jademcosta Date: Fri, 6 May 2022 18:11:52 -0300 Subject: [PATCH 14/36] Use DirDelim instead of magic string Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index adaf8da2b5..446cc2f60e 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -12,19 +12,19 @@ type PrefixedBucket struct { } func NewPrefixedBucket(bkt Bucket, prefix string) Bucket { - pbkt := &PrefixedBucket{bkt: bkt, prefix: strings.Trim(prefix, "/")} + pbkt := &PrefixedBucket{bkt: bkt, prefix: strings.Trim(prefix, DirDelim)} return pbkt } func conditionalPrefix(prefix, name string) string { if len(name) > 0 && len(prefix) > 0 { - return prefix + "/" + name + return prefix + DirDelim + name } return name } func withPrefix(prefix, name string) string { - return prefix + "/" + name + return prefix + DirDelim + name } func (p *PrefixedBucket) Close() error { @@ -39,7 +39,7 @@ func (p *PrefixedBucket) Iter(ctx context.Context, dir string, f func(string) er pdir := withPrefix(p.prefix, dir) return p.bkt.Iter(ctx, pdir, func(s string) error { - return f(strings.TrimPrefix(s, p.prefix+"/")) + return f(strings.TrimPrefix(s, p.prefix+DirDelim)) }, options...) } return p.bkt.Iter(ctx, dir, f, options...) From ba98b22e98a186fabf423e353ca31764fbf55bb4 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Fri, 6 May 2022 18:26:28 -0300 Subject: [PATCH 15/36] Add log when using prefixed bucket Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index dece31ce99..384e470eaa 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -87,8 +87,9 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe } var prefixedBucket objstore.Bucket - if ValidPrefix(bucketConf.Config.Prefix) { + if validPrefix(bucketConf.Config.Prefix) { prefixedBucket = objstore.NewPrefixedBucket(bucket, bucketConf.Config.Prefix) + level.Debug(logger).Log("msg", "using prefix on bucket access", "prefix", bucketConf.Config.Prefix) } else { prefixedBucket = bucket } @@ -96,7 +97,7 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), prefixedBucket, reg)), nil } -func ValidPrefix(prefix string) bool { +func validPrefix(prefix string) bool { prefix = strings.Replace(prefix, "/", "", -1) return len(prefix) > 0 } From d4acbb73d85076ecb84d0b01774dc16fb8711ceb Mon Sep 17 00:00:00 2001 From: jademcosta Date: Fri, 6 May 2022 18:38:26 -0300 Subject: [PATCH 16/36] Remove "@" from test string to make them simpler Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index 64792f5524..d331297cdd 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -38,7 +38,7 @@ func TestPrefixedBucket_Acceptance(t *testing.T) { } func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { - bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/file1.jpg", strings.NewReader("@test-data1")) + bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/file1.jpg", strings.NewReader("test-data1")) pBkt := NewPrefixedBucket(bkt, prefix) rc1, err := pBkt.Get(context.Background(), "file1.jpg") @@ -47,16 +47,16 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { defer func() { testutil.Ok(t, rc1.Close()) }() content, err := ioutil.ReadAll(rc1) testutil.Ok(t, err) - testutil.Equals(t, "@test-data1", string(content)) + testutil.Equals(t, "test-data1", string(content)) - pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("@test-data2")) + pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("test-data2")) rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") testutil.Ok(t, err) defer func() { testutil.Ok(t, rc2.Close()) }() contentUpload, err := ioutil.ReadAll(rc2) testutil.Ok(t, err) - testutil.Equals(t, "@test-data2", string(contentUpload)) + testutil.Equals(t, "test-data2", string(contentUpload)) pBkt.Delete(context.Background(), "file2.jpg") _, err = bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") @@ -69,7 +69,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { defer func() { testutil.Ok(t, rc3.Close()) }() content, err = ioutil.ReadAll(rc3) testutil.Ok(t, err) - testutil.Equals(t, "tes", string(content)) + testutil.Equals(t, "est", string(content)) ok, err := pBkt.Exists(context.Background(), "file1.jpg") testutil.Ok(t, err) @@ -77,9 +77,9 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { attrs, err := pBkt.Attributes(context.Background(), "file1.jpg") testutil.Ok(t, err) - testutil.Assert(t, attrs.Size == 11, "expected size to be equal to 11") + testutil.Assert(t, attrs.Size == 10, "expected size to be equal to 10") - bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/dir/file1.jpg", strings.NewReader("@test-data1")) + bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/dir/file1.jpg", strings.NewReader("test-data1")) seen := []string{} testutil.Ok(t, pBkt.Iter(context.Background(), "", func(fn string) error { seen = append(seen, fn) From 517790007becb4b33088e7410653c87a7c814239 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Tue, 10 May 2022 18:22:06 -0300 Subject: [PATCH 17/36] fix BucketConfig Config type - back to interface Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/client/factory.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index 384e470eaa..7610f7cb3e 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -40,11 +40,7 @@ const ( type BucketConfig struct { Type ObjProvider `yaml:"type"` - Config Config `yaml:"config"` -} - -type Config struct { - Prefix string `yaml:"prefix" default:""` + Config interface{} `yaml:"config"` } // NewBucket initializes and returns new object storage clients. @@ -86,10 +82,11 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } + prefix := PrefixFromConfig(string(confContentYaml)) var prefixedBucket objstore.Bucket - if validPrefix(bucketConf.Config.Prefix) { - prefixedBucket = objstore.NewPrefixedBucket(bucket, bucketConf.Config.Prefix) - level.Debug(logger).Log("msg", "using prefix on bucket access", "prefix", bucketConf.Config.Prefix) + if validPrefix(prefix) { + prefixedBucket = objstore.NewPrefixedBucket(bucket, prefix) + level.Debug(logger).Log("msg", "using prefix on bucket access", "prefix", prefix) } else { prefixedBucket = bucket } @@ -101,3 +98,18 @@ func validPrefix(prefix string) bool { prefix = strings.Replace(prefix, "/", "", -1) return len(prefix) > 0 } + +func PrefixFromConfig(confYaml string) string { + bucketConf := &BucketConfig{} + err := yaml.UnmarshalStrict([]byte(confYaml), &bucketConf) + if err != nil { + return "" + } + + prefix, ok := bucketConf.Config.(map[interface{}]interface{})["prefix"] + if !ok { + return "" + } + + return prefix.(string) +} From 14db917d39bdedba87da44d7a1998283c9d59923 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Tue, 10 May 2022 21:54:49 -0300 Subject: [PATCH 18/36] add changelog Signed-off-by: Maria Eduarda Duarte --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 199dfec426..436be38de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re ## Unreleased +- [#5337](https://github.com/thanos-io/thanos/pull/5337) Thanos Object Store: Add the `prefix` option to buckets + ### Fixed - [#5339](https://github.com/thanos-io/thanos/pull/5339) Receive: Fix deadlock on interrupt in routerOnly mode - [#5357](https://github.com/thanos-io/thanos/pull/5357) Store: fix groupcache handling of slashes From c30eb10500b21880b2acec4707bd35e054770921 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Tue, 10 May 2022 23:29:39 -0300 Subject: [PATCH 19/36] add missing checks in UsesPrefixTest Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/prefixed_bucket_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index d331297cdd..a52348a871 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -42,6 +42,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { pBkt := NewPrefixedBucket(bkt, prefix) rc1, err := pBkt.Get(context.Background(), "file1.jpg") + testutil.Ok(t, err) testutil.Ok(t, err) defer func() { testutil.Ok(t, rc1.Close()) }() @@ -51,6 +52,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("test-data2")) rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") + testutil.Ok(t, err) testutil.Ok(t, err) defer func() { testutil.Ok(t, rc2.Close()) }() @@ -60,6 +62,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { pBkt.Delete(context.Background(), "file2.jpg") _, err = bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") + testutil.Ok(t, err) testutil.NotOk(t, err) testutil.Assert(t, pBkt.IsObjNotFoundErr(err), "expected not found error got %s", err) From 776c17ece827e9c6a05d60fc83995fe6a4fc197f Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Wed, 11 May 2022 08:41:09 -0300 Subject: [PATCH 20/36] fix linter and test errors Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/prefixed_bucket_test.go | 35 +++++++++++----------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index a52348a871..f705153ae4 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -12,33 +12,28 @@ import ( func TestPrefixedBucket_Acceptance(t *testing.T) { prefix := "/someprefix/anotherprefix/" - bkt := NewPrefixedBucket(NewInMemBucket(), prefix) - AcceptanceTest(t, bkt) - UsesPrefixTest(t, bkt, prefix) + AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) + UsesPrefixTest(t, NewInMemBucket(), prefix) prefix = "someprefix/anotherprefix/" - bkt = NewPrefixedBucket(NewInMemBucket(), prefix) - AcceptanceTest(t, bkt) - UsesPrefixTest(t, bkt, prefix) + AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) + UsesPrefixTest(t, NewInMemBucket(), prefix) prefix = "someprefix/anotherprefix" - bkt = NewPrefixedBucket(NewInMemBucket(), prefix) - AcceptanceTest(t, bkt) - UsesPrefixTest(t, bkt, prefix) + AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) + UsesPrefixTest(t, NewInMemBucket(), prefix) prefix = "someprefix/" - bkt = NewPrefixedBucket(NewInMemBucket(), prefix) - AcceptanceTest(t, bkt) - UsesPrefixTest(t, bkt, prefix) + AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) + UsesPrefixTest(t, NewInMemBucket(), prefix) prefix = "someprefix" - bkt = NewPrefixedBucket(NewInMemBucket(), prefix) - AcceptanceTest(t, bkt) - UsesPrefixTest(t, bkt, prefix) + AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) + UsesPrefixTest(t, NewInMemBucket(), prefix) } func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { - bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/file1.jpg", strings.NewReader("test-data1")) + testutil.Ok(t, bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/file1.jpg", strings.NewReader("test-data1"))) pBkt := NewPrefixedBucket(bkt, prefix) rc1, err := pBkt.Get(context.Background(), "file1.jpg") @@ -50,7 +45,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Ok(t, err) testutil.Equals(t, "test-data1", string(content)) - pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("test-data2")) + testutil.Ok(t, pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("test-data2"))) rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") testutil.Ok(t, err) @@ -60,10 +55,8 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Ok(t, err) testutil.Equals(t, "test-data2", string(contentUpload)) - pBkt.Delete(context.Background(), "file2.jpg") + testutil.Ok(t, pBkt.Delete(context.Background(), "file2.jpg")) _, err = bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") - testutil.Ok(t, err) - testutil.NotOk(t, err) testutil.Assert(t, pBkt.IsObjNotFoundErr(err), "expected not found error got %s", err) @@ -82,7 +75,7 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Ok(t, err) testutil.Assert(t, attrs.Size == 10, "expected size to be equal to 10") - bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/dir/file1.jpg", strings.NewReader("test-data1")) + testutil.Ok(t, bkt.Upload(context.Background(), strings.Trim(prefix, "/")+"/dir/file1.jpg", strings.NewReader("test-data1"))) seen := []string{} testutil.Ok(t, pBkt.Iter(context.Background(), "", func(fn string) error { seen = append(seen, fn) From 4ec141eaf9be0346e6b885db68fed1388397ec85 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 11 May 2022 09:14:26 -0300 Subject: [PATCH 21/36] Add license to new files Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket.go | 3 +++ pkg/objstore/prefixed_bucket_test.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 446cc2f60e..59298be97e 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -1,3 +1,6 @@ +// Copyright (c) The Thanos Authors. +// Licensed under the Apache License 2.0. + package objstore import ( diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index f705153ae4..c41a73b067 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -1,3 +1,6 @@ +// Copyright (c) The Thanos Authors. +// Licensed under the Apache License 2.0. + package objstore import ( From 6ee26384df3431b9fb3d4d3f906e2794df080768 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 11 May 2022 18:25:56 -0300 Subject: [PATCH 22/36] Remove autogenerated docs Signed-off-by: jademcosta --- docs/storage.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/storage.md b/docs/storage.md index 6da3c94f3d..4a2dd82bec 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -64,7 +64,6 @@ type: S3 config: bucket: "" endpoint: "" - prefix: "" region: "" aws_sdk_auth: false access_key: "" @@ -333,7 +332,6 @@ config: storage_account_key: "" container: "" endpoint: "" - prefix: "" max_retries: 0 msi_resource: "" user_assigned_id: "" @@ -388,7 +386,6 @@ config: password: "" domain_id: "" domain_name: "" - prefix: "" project_id: "" project_name: "" project_domain_id: "" @@ -416,7 +413,6 @@ config: region: "" app_id: "" endpoint: "" - prefix: "" secret_key: "" secret_id: "" http_config: @@ -448,7 +444,6 @@ config: bucket: "" access_key_id: "" access_key_secret: "" - prefix: "" ``` Use --objstore.config-file to reference to this configuration file. @@ -464,7 +459,6 @@ config: endpoint: "" access_key: "" secret_key: "" - prefix: "" ``` #### Filesystem @@ -477,7 +471,6 @@ NOTE: This storage type is experimental and might be inefficient. It is NOT advi type: FILESYSTEM config: directory: "" - prefix: "" ``` ### How to add a new client to Thanos? From 661b75545d40aea1ea4f4a43b8795e72f3ce2e45 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Tue, 17 May 2022 09:18:01 -0300 Subject: [PATCH 23/36] Remove duplicated transformation of string->[]byte Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index 7610f7cb3e..363674bf70 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -82,8 +82,9 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } - prefix := PrefixFromConfig(string(confContentYaml)) + prefix := prefixFromConfig(confContentYaml) var prefixedBucket objstore.Bucket + if validPrefix(prefix) { prefixedBucket = objstore.NewPrefixedBucket(bucket, prefix) level.Debug(logger).Log("msg", "using prefix on bucket access", "prefix", prefix) @@ -99,9 +100,10 @@ func validPrefix(prefix string) bool { return len(prefix) > 0 } -func PrefixFromConfig(confYaml string) string { +func prefixFromConfig(confYaml []byte) string { bucketConf := &BucketConfig{} - err := yaml.UnmarshalStrict([]byte(confYaml), &bucketConf) + err := yaml.UnmarshalStrict(confYaml, &bucketConf) + if err != nil { return "" } From bd05bd98b44769988993a3761378923d9f6f347d Mon Sep 17 00:00:00 2001 From: jademcosta Date: Tue, 17 May 2022 11:11:15 -0300 Subject: [PATCH 24/36] Add prefixed bucket on all e2e tests for S3 The idea is that if it works, we can add for all other providers. Signed-off-by: jademcosta --- pkg/objstore/objtesting/foreach.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/objstore/objtesting/foreach.go b/pkg/objstore/objtesting/foreach.go index 6d1cad859f..d4f285f0e8 100644 --- a/pkg/objstore/objtesting/foreach.go +++ b/pkg/objstore/objtesting/foreach.go @@ -95,6 +95,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) // This needs to be investigated more. testFn(t, bkt) + testFn(t, objstore.NewPrefixedBucket(bkt, "some_prefix")) }) } From 5c8baee736ef68c80410e09d65a9203bc5a24d1a Mon Sep 17 00:00:00 2001 From: jademcosta Date: Tue, 17 May 2022 16:00:18 -0300 Subject: [PATCH 25/36] Add e2e tests using prefixed bucket to all providers Signed-off-by: jademcosta --- pkg/objstore/objtesting/foreach.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/objstore/objtesting/foreach.go b/pkg/objstore/objtesting/foreach.go index d4f285f0e8..139e724271 100644 --- a/pkg/objstore/objtesting/foreach.go +++ b/pkg/objstore/objtesting/foreach.go @@ -64,6 +64,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) b, err := filesystem.NewBucket(dir) testutil.Ok(t, err) testFn(t, b) + testFn(t, objstore.NewPrefixedBucket(b, "some_prefix")) }) // Optional GCS. @@ -77,6 +78,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) // TODO(bwplotka): Add goleak when https://github.com/GoogleCloudPlatform/google-cloud-go/issues/1025 is resolved. testFn(t, bkt) + testFn(t, objstore.NewPrefixedBucket(bkt, "some_prefix")) }) } @@ -109,6 +111,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) defer closeFn() testFn(t, bkt) + testFn(t, objstore.NewPrefixedBucket(bkt, "some_prefix")) }) } @@ -122,6 +125,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) defer closeFn() testFn(t, container) + testFn(t, objstore.NewPrefixedBucket(container, "some_prefix")) }) } @@ -135,6 +139,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) defer closeFn() testFn(t, bkt) + testFn(t, objstore.NewPrefixedBucket(bkt, "some_prefix")) }) } @@ -148,6 +153,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) defer closeFn() testFn(t, bkt) + testFn(t, objstore.NewPrefixedBucket(bkt, "some_prefix")) }) } @@ -161,6 +167,7 @@ func ForeachStore(t *testing.T, testFn func(t *testing.T, bkt objstore.Bucket)) defer closeFn() testFn(t, bkt) + testFn(t, objstore.NewPrefixedBucket(bkt, "some_prefix")) }) } } From 2c4fbc47fa2206af2ce6723024dd63a9ef8348c8 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Fri, 20 May 2022 10:22:14 -0300 Subject: [PATCH 26/36] refactor: move validPrefix to prefixed_bucket logic Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/client/factory.go | 22 ++++------------------ pkg/objstore/prefixed_bucket.go | 12 ++++++++++-- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index 363674bf70..26eb160ac3 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -82,26 +82,12 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } - prefix := prefixFromConfig(confContentYaml) - var prefixedBucket objstore.Bucket - - if validPrefix(prefix) { - prefixedBucket = objstore.NewPrefixedBucket(bucket, prefix) - level.Debug(logger).Log("msg", "using prefix on bucket access", "prefix", prefix) - } else { - prefixedBucket = bucket - } - - return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), prefixedBucket, reg)), nil + prefix := prefixFromConfig(confContentYaml, bucketConf) + + return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), objstore.NewPrefixedBucket(bucket, prefix), reg)), nil } -func validPrefix(prefix string) bool { - prefix = strings.Replace(prefix, "/", "", -1) - return len(prefix) > 0 -} - -func prefixFromConfig(confYaml []byte) string { - bucketConf := &BucketConfig{} +func prefixFromConfig(confYaml []byte, bucketConf *BucketConfig) string { err := yaml.UnmarshalStrict(confYaml, &bucketConf) if err != nil { diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 59298be97e..51a3fe1af5 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -15,8 +15,16 @@ type PrefixedBucket struct { } func NewPrefixedBucket(bkt Bucket, prefix string) Bucket { - pbkt := &PrefixedBucket{bkt: bkt, prefix: strings.Trim(prefix, DirDelim)} - return pbkt + if validPrefix(prefix) { + return &PrefixedBucket{bkt: bkt, prefix: strings.Trim(prefix, DirDelim)} + } + + return bkt +} + +func validPrefix(prefix string) bool { + prefix = strings.Replace(prefix, "/", "", -1) + return len(prefix) > 0 } func conditionalPrefix(prefix, name string) string { From 5173567bc86b702e52ea373f2fb08584c4290157 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Mon, 23 May 2022 21:22:14 -0300 Subject: [PATCH 27/36] Enhance the documentation about prefix. Signed-off-by: jademcosta --- docs/storage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/storage.md b/docs/storage.md index 4a2dd82bec..fa1c988c8f 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -102,7 +102,7 @@ At a minimum, you will need to provide a value for the `bucket`, `endpoint`, `ac However if you set `aws_sdk_auth: true` Thanos will use the default authentication methods of the AWS SDK for go based on [known environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) (`AWS_PROFILE`, `AWS_WEB_IDENTITY_TOKEN_FILE` ... etc) and known AWS config files (~/.aws/config). If you turn this on, then the `bucket` and `endpoint` are the required config keys. -The field `prefix` can be used to transparently use prefixes in your S3 bucket. That way, you may point distinct Thanos instances to the same bucket, while avoiding one instance messing with the data from another instance. This allows multiple Thanos deployments to use the same bucket without having to list all the files in it when you point Thanos store to the bucket (even when you are using tenants feature). +The field `prefix` can be used to transparently use prefixes in your S3 bucket. This allows you to separate blocks coming from different sources into paths with different prefixes, making it easier to understand what's going on (i.e. you don't have to use Thanos tooling to know from where which blocks came). The AWS region to endpoint mapping can be found in this [link](https://docs.aws.amazon.com/general/latest/gr/s3.html). From 435c13028e1d2d7a87eafd4009c3cbd56867b4b3 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Mon, 23 May 2022 21:56:46 -0300 Subject: [PATCH 28/36] Fix format Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index 26eb160ac3..d527e1408c 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -83,7 +83,7 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe } prefix := prefixFromConfig(confContentYaml, bucketConf) - + return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), objstore.NewPrefixedBucket(bucket, prefix), reg)), nil } From 5c0c3cc5582ba61f704271f1408102a144d167ce Mon Sep 17 00:00:00 2001 From: jademcosta Date: Tue, 17 May 2022 16:03:16 -0300 Subject: [PATCH 29/36] Add prefix entry on bucket config example Signed-off-by: jademcosta --- docs/storage.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/storage.md b/docs/storage.md index fa1c988c8f..eefcbe9b2e 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -63,6 +63,7 @@ NOTE: Minio client was mainly for AWS S3, but it can be configured against other type: S3 config: bucket: "" + prefix: "" endpoint: "" region: "" aws_sdk_auth: false From e611858a9b8c95de6640eb7e18b6a00239a2f3ff Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 25 May 2022 15:14:37 -0300 Subject: [PATCH 30/36] Removing redundancies on prefix checks and tests We already check if the prefix if not empty when creating the bucket. Signed-off-by: jademcosta --- pkg/objstore/prefixed_bucket.go | 15 ++++++-------- pkg/objstore/prefixed_bucket_test.go | 31 ++++++++++------------------ 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index 51a3fe1af5..a5a809ac82 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -28,8 +28,8 @@ func validPrefix(prefix string) bool { } func conditionalPrefix(prefix, name string) string { - if len(name) > 0 && len(prefix) > 0 { - return prefix + DirDelim + name + if len(name) > 0 { + return withPrefix(prefix, name) } return name } @@ -46,14 +46,11 @@ func (p *PrefixedBucket) Close() error { // object name including the prefix of the inspected directory. // Entries are passed to function in sorted order. func (p *PrefixedBucket) Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error { - if len(p.prefix) > 0 { - pdir := withPrefix(p.prefix, dir) + pdir := withPrefix(p.prefix, dir) - return p.bkt.Iter(ctx, pdir, func(s string) error { - return f(strings.TrimPrefix(s, p.prefix+DirDelim)) - }, options...) - } - return p.bkt.Iter(ctx, dir, f, options...) + return p.bkt.Iter(ctx, pdir, func(s string) error { + return f(strings.TrimPrefix(s, p.prefix+DirDelim)) + }, options...) } // Get returns a reader for the given object name. diff --git a/pkg/objstore/prefixed_bucket_test.go b/pkg/objstore/prefixed_bucket_test.go index c41a73b067..6e93583052 100644 --- a/pkg/objstore/prefixed_bucket_test.go +++ b/pkg/objstore/prefixed_bucket_test.go @@ -14,25 +14,18 @@ import ( ) func TestPrefixedBucket_Acceptance(t *testing.T) { - prefix := "/someprefix/anotherprefix/" - AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) - UsesPrefixTest(t, NewInMemBucket(), prefix) - prefix = "someprefix/anotherprefix/" - AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) - UsesPrefixTest(t, NewInMemBucket(), prefix) - - prefix = "someprefix/anotherprefix" - AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) - UsesPrefixTest(t, NewInMemBucket(), prefix) - - prefix = "someprefix/" - AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) - UsesPrefixTest(t, NewInMemBucket(), prefix) - - prefix = "someprefix" - AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) - UsesPrefixTest(t, NewInMemBucket(), prefix) + prefixes := []string{ + "/someprefix/anotherprefix/", + "someprefix/anotherprefix/", + "someprefix/anotherprefix", + "someprefix/", + "someprefix"} + + for _, prefix := range prefixes { + AcceptanceTest(t, NewPrefixedBucket(NewInMemBucket(), prefix)) + UsesPrefixTest(t, NewInMemBucket(), prefix) + } } func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { @@ -50,8 +43,6 @@ func UsesPrefixTest(t *testing.T, bkt Bucket, prefix string) { testutil.Ok(t, pBkt.Upload(context.Background(), "file2.jpg", strings.NewReader("test-data2"))) rc2, err := bkt.Get(context.Background(), strings.Trim(prefix, "/")+"/file2.jpg") - testutil.Ok(t, err) - testutil.Ok(t, err) defer func() { testutil.Ok(t, rc2.Close()) }() contentUpload, err := ioutil.ReadAll(rc2) From 8926d2a5edd25cb0d03c038e724fe0d48da58eeb Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 25 May 2022 15:40:15 -0300 Subject: [PATCH 31/36] Remove redundant YAML unmarshal Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index d527e1408c..ccdbe78357 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -88,12 +88,6 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe } func prefixFromConfig(confYaml []byte, bucketConf *BucketConfig) string { - err := yaml.UnmarshalStrict(confYaml, &bucketConf) - - if err != nil { - return "" - } - prefix, ok := bucketConf.Config.(map[interface{}]interface{})["prefix"] if !ok { return "" From 39c8dbff86512c509c8e79ddfd9dcc1c3554c9e6 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Wed, 25 May 2022 15:52:55 -0300 Subject: [PATCH 32/36] Remove unused parameter Signed-off-by: jademcosta --- pkg/objstore/client/factory.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index ccdbe78357..650173f1d2 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -82,12 +82,12 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } - prefix := prefixFromConfig(confContentYaml, bucketConf) + prefix := prefixFromConfig(bucketConf) return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), objstore.NewPrefixedBucket(bucket, prefix), reg)), nil } -func prefixFromConfig(confYaml []byte, bucketConf *BucketConfig) string { +func prefixFromConfig(bucketConf *BucketConfig) string { prefix, ok := bucketConf.Config.(map[interface{}]interface{})["prefix"] if !ok { return "" From 3e04c412cab42929ce16918d1f4d6f81cb12d6c2 Mon Sep 17 00:00:00 2001 From: jademcosta Date: Thu, 26 May 2022 09:22:25 -0300 Subject: [PATCH 33/36] Remove docs that should be auto-geneated Signed-off-by: jademcosta --- docs/storage.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/storage.md b/docs/storage.md index eefcbe9b2e..fa1c988c8f 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -63,7 +63,6 @@ NOTE: Minio client was mainly for AWS S3, but it can be configured against other type: S3 config: bucket: "" - prefix: "" endpoint: "" region: "" aws_sdk_auth: false From e4a03da694f59c48b40b632a5bbee1e901b1c54c Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Tue, 31 May 2022 17:11:42 -0300 Subject: [PATCH 34/36] refactor: move prefix to config root level Signed-off-by: Maria Eduarda Duarte --- pkg/objstore/client/factory.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/pkg/objstore/client/factory.go b/pkg/objstore/client/factory.go index 650173f1d2..2061079014 100644 --- a/pkg/objstore/client/factory.go +++ b/pkg/objstore/client/factory.go @@ -41,6 +41,7 @@ const ( type BucketConfig struct { Type ObjProvider `yaml:"type"` Config interface{} `yaml:"config"` + Prefix string `yaml:"prefix" default:""` } // NewBucket initializes and returns new object storage clients. @@ -82,16 +83,5 @@ func NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registe return nil, errors.Wrap(err, fmt.Sprintf("create %s client", bucketConf.Type)) } - prefix := prefixFromConfig(bucketConf) - - return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), objstore.NewPrefixedBucket(bucket, prefix), reg)), nil -} - -func prefixFromConfig(bucketConf *BucketConfig) string { - prefix, ok := bucketConf.Config.(map[interface{}]interface{})["prefix"] - if !ok { - return "" - } - - return prefix.(string) + return objstore.NewTracingBucket(objstore.BucketWithMetrics(bucket.Name(), objstore.NewPrefixedBucket(bucket, bucketConf.Prefix), reg)), nil } From a7a9229a3fc9c52b8d7837428a0ff9c60f4eed0b Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Thu, 2 Jun 2022 07:43:51 -0300 Subject: [PATCH 35/36] add auto generated docs Signed-off-by: Maria Eduarda Duarte --- docs/components/receive.md | 1 + docs/components/sidecar.md | 1 + docs/components/store.md | 1 + docs/components/tools.md | 3 +++ docs/storage.md | 8 ++++++++ pkg/objstore/prefixed_bucket.go | 1 + 6 files changed, 15 insertions(+) diff --git a/docs/components/receive.md b/docs/components/receive.md index 16dfd8a42f..542546b6e1 100644 --- a/docs/components/receive.md +++ b/docs/components/receive.md @@ -44,6 +44,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` The example content of `hashring.json`: diff --git a/docs/components/sidecar.md b/docs/components/sidecar.md index 57b69311b4..7a7deeb8e9 100644 --- a/docs/components/sidecar.md +++ b/docs/components/sidecar.md @@ -56,6 +56,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` ## Upload compacted blocks diff --git a/docs/components/store.md b/docs/components/store.md index 1162ad9946..3071e7b928 100644 --- a/docs/components/store.md +++ b/docs/components/store.md @@ -15,6 +15,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` In general, an average of 6 MB of local disk space is required per TSDB block stored in the object storage bucket, but for high cardinality blocks with large label set it can even go up to 30MB and more. It is for the pre-computed index, which includes symbols and postings offsets as well as metadata JSON. diff --git a/docs/components/tools.md b/docs/components/tools.md index 80ceed9585..776164aeb0 100644 --- a/docs/components/tools.md +++ b/docs/components/tools.md @@ -101,6 +101,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` Bucket can be extended to add more subcommands that will be helpful when working with object storage buckets by adding a new command within [`/cmd/thanos/tools_bucket.go`](../../cmd/thanos/tools_bucket.go) . @@ -601,6 +602,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` ```$ mdox-exec="thanos tools bucket downsample --help" @@ -675,6 +677,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` ```$ mdox-exec="thanos tools bucket mark --help" diff --git a/docs/storage.md b/docs/storage.md index fa1c988c8f..47f2bd3f19 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -96,6 +96,7 @@ config: kms_encryption_context: {} encryption_key: "" sts_endpoint: "" +prefix: "" ``` At a minimum, you will need to provide a value for the `bucket`, `endpoint`, `access_key`, and `secret_key` keys. The rest of the keys are optional. @@ -257,6 +258,7 @@ type: GCS config: bucket: "" service_account: "" +prefix: "" ``` ##### Using GOOGLE_APPLICATION_CREDENTIALS @@ -358,6 +360,7 @@ config: key_file: "" server_name: "" insecure_skip_verify: false +prefix: "" ``` If `msi_resource` is used, authentication is done via system-assigned managed identity. The value for Azure should be `https://.blob.core.windows.net`. @@ -398,6 +401,7 @@ config: connect_timeout: 10s timeout: 5m use_dynamic_large_objects: false +prefix: "" ``` #### Tencent COS @@ -423,6 +427,7 @@ config: max_idle_conns: 100 max_idle_conns_per_host: 100 max_conns_per_host: 0 +prefix: "" ``` The `secret_key` and `secret_id` field is required. The `http_config` field is optional for optimize HTTP transport settings. There are two ways to configure the required bucket information: @@ -444,6 +449,7 @@ config: bucket: "" access_key_id: "" access_key_secret: "" +prefix: "" ``` Use --objstore.config-file to reference to this configuration file. @@ -459,6 +465,7 @@ config: endpoint: "" access_key: "" secret_key: "" +prefix: "" ``` #### Filesystem @@ -471,6 +478,7 @@ NOTE: This storage type is experimental and might be inefficient. It is NOT advi type: FILESYSTEM config: directory: "" +prefix: "" ``` ### How to add a new client to Thanos? diff --git a/pkg/objstore/prefixed_bucket.go b/pkg/objstore/prefixed_bucket.go index a5a809ac82..130f14d439 100644 --- a/pkg/objstore/prefixed_bucket.go +++ b/pkg/objstore/prefixed_bucket.go @@ -31,6 +31,7 @@ func conditionalPrefix(prefix, name string) string { if len(name) > 0 { return withPrefix(prefix, name) } + return name } From d72d6457fdac489acf9a8b24116cda00f7e41850 Mon Sep 17 00:00:00 2001 From: Maria Eduarda Duarte Date: Thu, 9 Jun 2022 16:25:16 -0300 Subject: [PATCH 36/36] fix changelog Signed-off-by: Maria Eduarda Duarte --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 436be38de2..b14a61df1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,13 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re ## Unreleased -- [#5337](https://github.com/thanos-io/thanos/pull/5337) Thanos Object Store: Add the `prefix` option to buckets - ### Fixed - [#5339](https://github.com/thanos-io/thanos/pull/5339) Receive: Fix deadlock on interrupt in routerOnly mode - [#5357](https://github.com/thanos-io/thanos/pull/5357) Store: fix groupcache handling of slashes ### Added +- [#5337](https://github.com/thanos-io/thanos/pull/5337) Thanos Object Store: Add the `prefix` option to buckets - [#5352](https://github.com/thanos-io/thanos/pull/5352) Cache: Add cache metrics to groupcache. - [#5391](https://github.com/thanos-io/thanos/pull/5391) Receive: Add relabeling support.