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

Add Huawei Cloud OBS Object Storage Support #50

Merged
merged 10 commits into from
May 22, 2023
Merged

Conversation

setoru
Copy link
Contributor

@setoru setoru commented Apr 27, 2023

Huawei Cloud is a public cloud provider in China, Its object storage product is OBS.

thanos is not supported OBS right now,This pr implements a OBS client and it seems to be ok.

I would like to become the maintainer for the OBS provider and keep development for Thanos.

  • I added CHANGELOG entry for this change.
  • Change is not relevant to the end user.

Changes

  • Implement Bucket interface
  • Add NewTestBucket constructor
  • Pass the ForeachStore test
  • Add client implementation to the factory
  • Add client struct config to bucketcfggen

Verification

image

Signed-off-by: setoru <setoru127@gmail.com>
Signed-off-by: setoru <setoru127@gmail.com>
Signed-off-by: setoru <setoru127@gmail.com>
Signed-off-by: setoru <setoru127@gmail.com>
Signed-off-by: setoru <setoru127@gmail.com>
Copy link
Contributor

@matej-g matej-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! For now I skimmed through the PR, few suggestions. It also looks like the tests and lint are failing for now.

@@ -4,6 +4,7 @@
package objtesting

import (
"github.com/thanos-io/objstore/providers/obs"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can we keep imports grouping? i.e. move this down to the last group.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure can,I will fix it.

providers/obs/obs.go Show resolved Hide resolved
@@ -5,6 +5,7 @@ package main

import (
"fmt"
"github.com/thanos-io/objstore/providers/obs"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: same as previous (import grouping)

@@ -6,6 +6,7 @@ package client
import (
"context"
"fmt"
"github.com/thanos-io/objstore/providers/obs"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Import ordering

Comment on lines 186 to 187
_, err := b.client.PutObject(input)
return errors.Wrap(err, "fail to upload object")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If find doing if err != nil { return errors.Wrap(...) } to be a readable a bit better rather than returning directly errors.Wrap.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right,I will fix it

Comment on lines 194 to 195
initOutput, err := b.client.InitiateMultipartUpload(initInput)
return initOutput, errors.Wrap(err, "fail to init multipart upload job")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as previous comment (Doing if err != nil { return errors.Wrap(...) } rather than directly returning wrap).

Signed-off-by: setoru <setoru127@gmail.com>
Signed-off-by: setoru <setoru127@gmail.com>
@setoru setoru requested a review from matej-g May 4, 2023 01:32
Signed-off-by: setoru <setoru127@gmail.com>
Copy link
Contributor

@matej-g matej-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good, thank you! I have added couple more suggestions after second review.

Comment on lines 294 to 298
if length != -1 {
input.RangeEnd = off + length - 1
} else {
input.RangeEnd = math.MaxInt64
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Small readability improvement suggestion.

Suggested change
if length != -1 {
input.RangeEnd = off + length - 1
} else {
input.RangeEnd = math.MaxInt64
}
input.RangeEnd = math.MaxInt64
if length != -1 {
input.RangeEnd = off + length - 1
}

Parts: parts,
})
if err != nil {
return errors.Wrap(err, "fail to complete multipart upload")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could we make all comments say failed instead of fail

Suggested change
return errors.Wrap(err, "fail to complete multipart upload")
return errors.Wrap(err, "failed to complete multipart upload")

}
for _, content := range output.Contents {
if err := f(content.Key); err != nil {
return errors.Wrap(err, "fail to call f for object")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make this a bit more user friendly, something along to lines failed to call iter function for object X?

README.md Outdated
@@ -640,6 +641,41 @@ config:

You can also include any of the optional configuration just like the example in `Default Provider`.

##### HuaweiCloud OBS

To use HuaweiCloud OBS as storage store, you should apply a HuaweiCloud Account to create an object storage bucket at first.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To use HuaweiCloud OBS as storage store, you should apply a HuaweiCloud Account to create an object storage bucket at first.
To use HuaweiCloud OBS as an object store, you should apply for a HuaweiCloud Account to create an object storage bucket at first.

README.md Outdated
##### HuaweiCloud OBS

To use HuaweiCloud OBS as storage store, you should apply a HuaweiCloud Account to create an object storage bucket at first.
Note that detailed from [HuaweiCloud OBS](https://support.huaweicloud.com/obs/index.html)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Note that detailed from [HuaweiCloud OBS](https://support.huaweicloud.com/obs/index.html)
More details: [HuaweiCloud OBS](https://support.huaweicloud.com/obs/index.html)

README.md Outdated
To use HuaweiCloud OBS as storage store, you should apply a HuaweiCloud Account to create an object storage bucket at first.
Note that detailed from [HuaweiCloud OBS](https://support.huaweicloud.com/obs/index.html)

To configure HuaweiCloud Account to use OBS as storage store you need to set these parameters in yaml format stored in a file:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To configure HuaweiCloud Account to use OBS as storage store you need to set these parameters in yaml format stored in a file:
To configure HuaweiCloud Account to use OBS as storage store you need to set these parameters in YAML format stored in a file:

Comment on lines 323 to 325
switch oriErr := errors.Cause(err).(type) {
case obs.ObsError:
if oriErr.Status == "404 Not Found" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have only one case, why not do oriErr, ok := errors.Cause(err).(obs.ObsError)?

Signed-off-by: setoru <setoru127@gmail.com>
@setoru setoru requested a review from matej-g May 5, 2023 03:18
}
for _, content := range output.Contents {
if err := f(content.Key); err != nil {
return errors.Wrap(err, "fail to call f for object")
return errors.Wrap(err, "failed to call iter function for object X")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean here instead of X, you could use content.Key to signal which object the function failed for?

}
}
for _, topDir := range output.CommonPrefixes {
if err := f(topDir); err != nil {
return errors.Wrap(err, "fail to call f for top dir object")
return errors.Wrap(err, "failed to call f for top dir object")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we adjust this the same way as my previous comment (don't say failed to call f ... but rather failed to call iter function)

Signed-off-by: setoru <setoru127@gmail.com>
@setoru setoru requested a review from matej-g May 6, 2023 01:19
Copy link
Contributor

@matej-g matej-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good now, thank you @setoru! 🙇

@setoru
Copy link
Contributor Author

setoru commented May 19, 2023

Thank you for reviewing!

@matej-g matej-g merged commit 23ebe2e into thanos-io:main May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants