fix(region): vendor update (#23652)

This commit is contained in:
屈轩
2025-11-01 13:03:50 +08:00
committed by GitHub
parent 07d1cecf99
commit 41c5c66fe2
18 changed files with 897 additions and 93 deletions
+1 -1
View File
@@ -98,7 +98,7 @@ require (
k8s.io/cri-api v0.28.15
k8s.io/klog/v2 v2.20.0
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251029113936-04a08ceb0273
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251031063556-cfcc66d60507
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
+2 -2
View File
@@ -1470,8 +1470,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251029113936-04a08ceb0273 h1:0AsTwn72zovuZ7sGQJ+yqCCe71AnzlX/BQT9AtKX+Xo=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251029113936-04a08ceb0273/go.mod h1:nya/IL1IXSMmFgB48P27CppyGpkT5coG150PD+xVJrc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251031063556-cfcc66d60507 h1:g0nP+pDPhwH9wgQDtwIcW/u+3lBzIkqQE8qwPpGLi1g=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251031063556-cfcc66d60507/go.mod h1:MeA5UnvNhLXMvy+xPMOzRqjWMWMkZ3QXZP0u1bYEM0M=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
+1 -1
View File
@@ -2039,7 +2039,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251029113936-04a08ceb0273
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251031063556-cfcc66d60507
## explicit; go 1.24
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
+26
View File
@@ -672,3 +672,29 @@ func (self *SRegion) RemoveRdsTagsFromResource(arn string, tags map[string]strin
}
return self.rdsRequest("RemoveTagsFromResource", params, nil)
}
type SEngineVersion struct {
EngineVersion string
Status string
}
func (region *SRegion) DescribeDBEngineVersions(engine string) ([]SEngineVersion, error) {
params := map[string]string{}
ret := []SEngineVersion{}
for {
part := struct {
DBEngineVersions []SEngineVersion `xml:"DBEngineVersions>DBEngineVersion"`
Marker string `xml:"Marker"`
}{}
err := region.rdsRequest("DescribeDBEngineVersions", params, &part)
if err != nil {
return nil, errors.Wrapf(err, "DescribeDBEngineVersions")
}
ret = append(ret, part.DBEngineVersions...)
if len(part.DBEngineVersions) == 0 || len(part.Marker) == 0 {
break
}
params["Marker"] = part.Marker
}
return ret, nil
}
+5 -1
View File
@@ -137,7 +137,7 @@ func (self *SRegion) GetInstanceType(name string) (*InstanceType, error) {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", name)
}
func (self *SRegion) GetInstanceTypes() ([]SInstanceType, error) {
func (self *SRegion) GetInstanceTypes(instanceType string) ([]SInstanceType, error) {
filters := map[string]string{
"regionCode": self.RegionId,
"operatingSystem": "Linux",
@@ -149,6 +149,10 @@ func (self *SRegion) GetInstanceTypes() ([]SInstanceType, error) {
"capacitystatus": "Used",
}
if len(instanceType) > 0 {
filters["instanceType"] = instanceType
}
params := []ProductFilter{}
for k, v := range filters {
+73 -48
View File
@@ -18,6 +18,7 @@ import (
"context"
"crypto/tls"
"fmt"
"io"
"net/http"
"net/url"
"strings"
@@ -25,7 +26,6 @@ import (
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/httputils"
@@ -123,7 +123,7 @@ func (cli *SBaiduClient) GetRegion(id string) (*SRegion, error) {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
}
func (cli *SBaiduClient) getUrl(service, regionId, resource string) (string, error) {
func (cli *SBaiduClient) getUrl(service, regionId, bucketName, resource string) (string, error) {
if len(regionId) == 0 {
regionId = BAIDU_DEFAULT_REGION
}
@@ -133,7 +133,10 @@ func (cli *SBaiduClient) getUrl(service, regionId, resource string) (string, err
case SERVICE_BCC:
return fmt.Sprintf("https://bcc.%s.baidubce.com/%s", regionId, strings.TrimPrefix(resource, "/")), nil
case SERVICE_BOS:
return fmt.Sprintf("https://%s.bcebos.com", regionId), nil
if len(bucketName) > 0 {
return fmt.Sprintf("https://%s.%s.bcebos.com/%s", bucketName, regionId, strings.TrimPrefix(resource, "/")), nil
}
return fmt.Sprintf("https://%s.bcebos.com/%s", regionId, strings.TrimPrefix(resource, "/")), nil
case SERVICE_BILLING:
return fmt.Sprintf("https://billing.baidubce.com/%s", strings.TrimPrefix(resource, "/")), nil
case SERVICE_STS:
@@ -169,46 +172,39 @@ func (cli *SBaiduClient) getDefaultClient() *http.Client {
return cli.client
}
type sBaiduError struct {
StatusCode int `json:"statusCode"`
RequestId string `json:"requestId"`
Code string
Message string
method httputils.THttpMethod
url string
body jsonutils.JSONObject
}
func (e *sBaiduError) Error() string {
return jsonutils.Marshal(e).String()
}
func (e *sBaiduError) ParseErrorFromJsonResponse(statusCode int, status string, body jsonutils.JSONObject) error {
if body != nil {
body.Unmarshal(e)
}
e.StatusCode = statusCode
log.Infof("%s %s body: %s error: %v", e.method, e.url, e.body, e.Error())
if e.StatusCode == 404 {
return errors.Wrapf(cloudprovider.ErrNotFound, "%s", e.Error())
}
return e
}
func (cli *SBaiduClient) Do(req *http.Request) (*http.Response, error) {
client := cli.getDefaultClient()
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.Header.Set("x-bce-date", time.Now().UTC().Format(ISO8601))
req.Header.Set("host", req.Host)
signature, err := cli.sign(req)
func (cli *SBaiduClient) bosList(regionId, bucketName, resource string, params url.Values) (jsonutils.JSONObject, error) {
resp, err := cli.raw_request(httputils.GET, SERVICE_BOS, regionId, bucketName, resource, params, nil, nil)
if err != nil {
return nil, errors.Wrapf(err, "sign")
return nil, err
}
_, ret, err := httputils.ParseJSONResponse("", resp, err, cli.debug)
return ret, err
}
req.Header.Set("Authorization", signature)
return client.Do(req)
func (cli *SBaiduClient) bosDelete(regionId, bucketName, resource string, params url.Values) (jsonutils.JSONObject, error) {
resp, err := cli.raw_request(httputils.DELETE, SERVICE_BOS, regionId, bucketName, resource, params, nil, nil)
if err != nil {
return nil, err
}
_, ret, err := httputils.ParseJSONResponse("", resp, err, cli.debug)
return ret, err
}
func (cli *SBaiduClient) bosUpdate(regionId, bucketName, resource string, params url.Values, body map[string]interface{}) (jsonutils.JSONObject, error) {
var bodyReader io.Reader = nil
if !gotypes.IsNil(body) {
bodyReader = strings.NewReader(jsonutils.Marshal(body).String())
}
resp, err := cli.raw_request(httputils.PUT, SERVICE_BOS, regionId, bucketName, resource, params, nil, bodyReader)
if err != nil {
return nil, err
}
_, ret, err := httputils.ParseJSONResponse("", resp, err, cli.debug)
return ret, err
}
func (cli *SBaiduClient) bosRequest(method httputils.THttpMethod, regionId, bucketName, resource string, params url.Values, header http.Header, body io.Reader) (*http.Response, error) {
return cli.raw_request(method, SERVICE_BOS, regionId, bucketName, resource, params, header, body)
}
func (cli *SBaiduClient) eipList(regionId, resource string, params url.Values) (jsonutils.JSONObject, error) {
@@ -264,21 +260,49 @@ func (cli *SBaiduClient) post(service, regionId, resource string, params url.Val
}
func (cli *SBaiduClient) request(method httputils.THttpMethod, service, regionId, resource string, params url.Values, body map[string]interface{}) (jsonutils.JSONObject, error) {
uri, err := cli.getUrl(service, regionId, resource)
var bodyReader io.Reader = nil
if !gotypes.IsNil(body) {
bodyReader = strings.NewReader(jsonutils.Marshal(body).String())
}
header := http.Header{}
header.Set("Content-Type", "application/json; charset=utf-8")
resp, err := cli.raw_request(method, service, regionId, "", resource, params, header, bodyReader)
if err != nil {
return nil, err
}
if body == nil {
body = map[string]interface{}{}
_, ret, err := httputils.ParseJSONResponse("", resp, err, cli.debug)
return ret, err
}
func (cli *SBaiduClient) raw_request(method httputils.THttpMethod, service, regionId, bucketName, resource string, params url.Values, header http.Header, body io.Reader) (*http.Response, error) {
uri, err := cli.getUrl(service, regionId, bucketName, resource)
if err != nil {
return nil, err
}
if len(params) > 0 {
uri = fmt.Sprintf("%s?%s", uri, params.Encode())
}
req := httputils.NewJsonRequest(method, uri, body)
bErr := &sBaiduError{method: method, url: uri, body: jsonutils.Marshal(body)}
client := httputils.NewJsonClient(cli)
_, resp, err := client.Send(cli.ctx, req, bErr, cli.debug)
return resp, err
if gotypes.IsNil(header) {
header = http.Header{}
}
burl, err := url.Parse(uri)
if err != nil {
return nil, err
}
header.Set("x-bce-date", time.Now().UTC().Format(ISO8601))
header.Set("host", burl.Host)
signature, err := cli.sign(burl, string(method), header)
if err != nil {
return nil, errors.Wrapf(err, "sign raw request")
}
header.Set("Authorization", signature)
return httputils.Request(cli.getDefaultClient(), cli.ctx, method, uri, header, body, cli.debug)
}
func (cli *SBaiduClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
@@ -331,6 +355,7 @@ func (cli *SBaiduClient) GetCapabilities() []string {
cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP,
cloudprovider.CLOUD_CAPABILITY_EIP,
cloudprovider.CLOUD_CAPABILITY_SNAPSHOT_POLICY,
cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE,
}
return caps
}
+591
View File
@@ -0,0 +1,591 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package baidu
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/httputils"
)
type SBucket struct {
multicloud.SBaseBucket
multicloud.STagBase
region *SRegion
Name string
Location string
CreationDate time.Time
}
func (b *SBucket) GetId() string {
return b.Name
}
func (b *SBucket) GetGlobalId() string {
return b.Name
}
func (b *SBucket) GetName() string {
return b.Name
}
func (b *SBucket) GetLocation() string {
return b.Location
}
func (b *SBucket) GetCreatedAt() time.Time {
return b.CreationDate
}
func (b *SBucket) GetStorageClass() string {
storageClass, err := b.region.GetBucketStorageClass(b.Name)
if err != nil {
return ""
}
return storageClass
}
func (b *SBucket) GetAcl() cloudprovider.TBucketACLType {
acl, err := b.region.GetBucketAcl(b.Name)
if err != nil {
return cloudprovider.ACLUnknown
}
return acl.GetAcl()
}
func (b *SBucket) SetAcl(acl cloudprovider.TBucketACLType) error {
return b.region.SetBucketAcl(b.Name, acl)
}
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
return []cloudprovider.SBucketAccessUrl{
{
Url: fmt.Sprintf("https://%s.%s.bcebos.com", b.Name, b.region.GetId()),
Description: "ExtranetEndpoint",
Primary: true,
},
}
}
func (b *SBucket) GetTags() (map[string]string, error) {
params := url.Values{}
params.Set("tagging", "")
resp, err := b.region.bosRequest(httputils.GET, b.Name, "", params, http.Header{}, nil)
if err != nil {
return nil, errors.Wrap(err, "GetTags")
}
_, body, err := httputils.ParseJSONResponse("", resp, nil, b.region.client.debug)
if err != nil {
return nil, errors.Wrap(err, "ParseJSONResponse")
}
ret := struct {
Tag []struct {
TagKey string `json:"tagKey"`
TagValue string `json:"tagValue"`
} `json:"tag"`
}{}
err = body.Unmarshal(&ret)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
res := map[string]string{}
for _, tag := range ret.Tag {
res[tag.TagKey] = tag.TagValue
}
return res, nil
}
func (b *SBucket) SetTags(tags map[string]string, replace bool) error {
params := url.Values{}
params.Set("tagging", "")
_, err := b.region.bosRequest(httputils.DELETE, b.Name, "", params, http.Header{}, nil)
if err != nil {
return errors.Wrap(err, "DeleteTagging")
}
if len(tags) == 0 {
return nil
}
input := []map[string]string{}
for k, v := range tags {
input = append(input, map[string]string{
"tagKey": k,
"tagValue": v,
})
}
body := strings.NewReader(jsonutils.Marshal(map[string]interface{}{"tags": input}).String())
_, err = b.region.bosRequest(httputils.PUT, b.Name, "", params, http.Header{}, body)
if err != nil {
return errors.Wrap(err, "SetTags")
}
return nil
}
func (b *SBucket) GetStats() cloudprovider.SBucketStats {
stat, _ := cloudprovider.GetIBucketStats(b)
return stat
}
func (b *SBucket) SetLimit(limit cloudprovider.SBucketStats) error {
return b.region.SetBucketLimit(b.Name, limit)
}
func (region *SRegion) SetBucketLimit(bucketName string, limit cloudprovider.SBucketStats) error {
params := url.Values{}
params.Set("quota", "")
body := map[string]interface{}{
"maxObjectCount": limit.ObjectCount,
"maxCapacityMegaBytes": limit.SizeBytes,
}
_, err := region.bosUpdate(bucketName, "", params, body)
return err
}
func (b *SBucket) LimitSupport() cloudprovider.SBucketStats {
ret, err := b.region.GetBucketLimit(b.Name)
if err != nil {
return cloudprovider.SBucketStats{
ObjectCount: -1,
SizeBytes: -1,
}
}
return ret
}
func (region *SRegion) GetBucketLimit(bucketName string) (cloudprovider.SBucketStats, error) {
params := url.Values{}
params.Set("quota", "")
resp, err := region.bosList(bucketName, "", params)
if err != nil {
return cloudprovider.SBucketStats{}, err
}
ret := struct {
MaxObjectCount int
MaxCapacityMegaBytes int
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return cloudprovider.SBucketStats{
ObjectCount: -1,
SizeBytes: -1,
}, err
}
return cloudprovider.SBucketStats{
ObjectCount: ret.MaxObjectCount,
SizeBytes: int64(ret.MaxCapacityMegaBytes),
}, nil
}
func (b *SBucket) CopyObject(ctx context.Context, destKey string, srcBucket, srcKey string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error {
header := http.Header{}
if len(cannedAcl) > 0 {
header.Set("x-bce-acl", string(cannedAcl))
}
if len(storageClassStr) > 0 {
header.Set("x-bce-storage-class", storageClassStr)
}
if len(srcBucket) > 0 {
header.Set("x-bce-copy-source", fmt.Sprintf("%s/%s", url.PathEscape(srcBucket), url.PathEscape(srcKey)))
}
for k := range meta {
header.Set(k, meta.Get(k))
}
resp, err := b.region.bosRequest(httputils.PUT, b.Name, destKey, url.Values{}, header, nil)
if err != nil {
return errors.Wrapf(err, "CopyObject %s %s %s %s", b.Name, destKey, srcBucket, srcKey)
}
defer httputils.CloseResponse(resp)
return nil
}
func (b *SBucket) GetObject(ctx context.Context, key string, rangeOpt *cloudprovider.SGetObjectRange) (io.ReadCloser, error) {
header := http.Header{}
if rangeOpt != nil {
header.Set("Range", rangeOpt.String())
}
resp, err := b.region.bosRequest(httputils.GET, b.Name, key, url.Values{}, header, nil)
if err != nil {
return nil, errors.Wrapf(err, "GetObject %s %s", b.Name, key)
}
return resp.Body, nil
}
func (b *SBucket) DeleteObject(ctx context.Context, key string) error {
return b.region.DeleteObject(b.Name, key)
}
func (region *SRegion) DeleteObject(bucketName, key string) error {
resp, err := region.bosRequest(httputils.DELETE, bucketName, key, url.Values{}, http.Header{}, nil)
if err != nil {
return errors.Wrapf(err, "DeleteObject %s %s", bucketName, key)
}
httputils.CloseResponse(resp)
return nil
}
func (b *SBucket) GetTempUrl(method string, key string, expire time.Duration) (string, error) {
uri, err := url.Parse(fmt.Sprintf("https://%s.%s.bcebos.com/%s", b.Name, b.region.GetId(), url.PathEscape(key)))
if err != nil {
return "", errors.Wrapf(err, "Parse %s %s", b.Name, b.region.GetId())
}
header := http.Header{}
sign, err := b.region.client._sign(uri, method, header, int(expire.Seconds()))
if err != nil {
return "", errors.Wrapf(err, "Sign %s %s", b.Name, key)
}
query := url.Values{}
query.Set("authorization", sign)
return fmt.Sprintf("%s?%s", uri.String(), query.Encode()), nil
}
func (b *SBucket) PutObject(ctx context.Context, key string, input io.Reader, sizeBytes int64, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error {
header := http.Header{}
if len(cannedAcl) > 0 {
header.Set("x-bce-acl", string(cannedAcl))
}
if len(storageClassStr) > 0 {
header.Set("x-bce-storage-class", storageClassStr)
}
for k := range meta {
header.Set(fmt.Sprintf("x-bce-meta-%s", k), meta.Get(k))
}
if sizeBytes > 0 {
header.Set("Content-Length", strconv.FormatInt(sizeBytes, 10))
}
resp, err := b.region.bosRequest(httputils.PUT, b.Name, key, url.Values{}, header, input)
if err != nil {
return errors.Wrapf(err, "PutObject %s %s", b.Name, key)
}
httputils.CloseResponse(resp)
return nil
}
const (
THRESHOLD_100_CONTINUE = 1 << 20
)
func (b *SBucket) NewMultipartUpload(ctx context.Context, key string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) (string, error) {
header := http.Header{}
if len(cannedAcl) > 0 {
header.Set("x-bce-acl", string(cannedAcl))
}
if len(storageClassStr) > 0 {
header.Set("x-bce-storage-class", storageClassStr)
}
for k := range meta {
header.Set(fmt.Sprintf("x-bce-meta-%s", k), meta.Get(k))
}
params := url.Values{}
params.Set("uploads", "")
resp, err := b.region.bosRequest(httputils.POST, b.Name, key, params, header, nil)
if err != nil {
return "", errors.Wrapf(err, "NewMultipartUpload %s %s", b.Name, key)
}
_, body, err := httputils.ParseJSONResponse("", resp, nil, b.region.client.debug)
if err != nil {
return "", errors.Wrapf(err, "ParseJSONResponse %s %s", b.Name, key)
}
return body.GetString("uploadId")
}
func (b *SBucket) UploadPart(ctx context.Context, key string, uploadId string, partIndex int, input io.Reader, partSize int64, offset, totalSize int64) (string, error) {
header := http.Header{}
header.Set("Content-Length", strconv.FormatInt(partSize, 10))
params := url.Values{}
params.Set("uploadId", uploadId)
params.Set("partNumber", strconv.Itoa(partIndex))
if partSize > THRESHOLD_100_CONTINUE {
header.Set("Expect", "100-continue")
}
resp, err := b.region.bosRequest(httputils.PUT, b.Name, key, params, header, input)
if err != nil {
return "", errors.Wrapf(err, "UploadPart %s %s %s", b.Name, key, uploadId)
}
defer httputils.CloseResponse(resp)
return strings.Trim(resp.Header.Get("ETag"), "\""), nil
}
func (b *SBucket) CompleteMultipartUpload(ctx context.Context, key string, uploadId string, partEtags []string) error {
header := http.Header{}
params := url.Values{}
params.Set("uploadId", uploadId)
parts := []map[string]string{}
for i, etag := range partEtags {
parts = append(parts, map[string]string{
"partNumber": strconv.Itoa(i + 1),
"eTag": etag,
})
}
body := strings.NewReader(jsonutils.Marshal(map[string]interface{}{"parts": parts}).String())
resp, err := b.region.bosRequest(httputils.POST, b.Name, key, params, header, body)
if err != nil {
return errors.Wrapf(err, "CompleteMultipartUpload %s %s %s", b.Name, key, uploadId)
}
httputils.CloseResponse(resp)
return nil
}
func (b *SBucket) AbortMultipartUpload(ctx context.Context, key string, uploadId string) error {
params := url.Values{}
params.Set("uploadId", uploadId)
resp, err := b.region.bosRequest(httputils.DELETE, b.Name, key, params, http.Header{}, nil)
if err != nil {
return errors.Wrapf(err, "AbortMultipartUpload %s %s %s", b.Name, key, uploadId)
}
httputils.CloseResponse(resp)
return nil
}
func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, partIndex int, srcBucket string, srcKey string, srcOffset int64, srcLength int64) (string, error) {
header := http.Header{}
params := url.Values{}
params.Set("uploadId", uploadId)
params.Set("partNumber", strconv.Itoa(partIndex))
header.Set("x-bce-copy-source", fmt.Sprintf("%s/%s", url.PathEscape(srcBucket), url.PathEscape(srcKey)))
if srcLength > 0 {
header.Set("x-bce-copy-source-range", fmt.Sprintf("bytes=%d-%d", srcOffset, srcOffset+srcLength-1))
}
resp, err := b.region.bosRequest(httputils.PUT, b.Name, key, params, header, nil)
if err != nil {
return "", errors.Wrapf(err, "CopyPart %s %s %s %s %d %d", b.Name, key, uploadId, srcBucket, srcOffset, srcLength)
}
_, body, err := httputils.ParseJSONResponse("", resp, nil, b.region.client.debug)
if err != nil {
return "", errors.Wrapf(err, "ParseJSONResponse %s %s %s", b.Name, key, uploadId)
}
return body.GetString("eTag")
}
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
return b.region
}
func (b *SBucket) GetProjectId() string {
return ""
}
func (b *SBucket) ListObjects(prefix string, marker string, delimiter string, maxCount int) (cloudprovider.SListObjectResult, error) {
params := url.Values{}
if len(delimiter) > 0 {
params.Set("delimiter", delimiter)
}
if len(prefix) > 0 {
params.Set("prefix", prefix)
}
if maxCount > 0 {
params.Set("maxKeys", strconv.Itoa(maxCount))
}
if len(marker) > 0 {
params.Set("marker", marker)
}
resp, err := b.region.bosList(b.Name, "", params)
if err != nil {
return cloudprovider.SListObjectResult{}, err
}
ret := struct {
Name string
Prefix string
IsTruncated bool
Marker string
CommonPrefixes []struct {
Prefix string
}
Contents []SObject
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return cloudprovider.SListObjectResult{}, err
}
result := cloudprovider.SListObjectResult{
Objects: make([]cloudprovider.ICloudObject, 0),
CommonPrefixes: make([]cloudprovider.ICloudObject, 0),
}
for _, content := range ret.Contents {
content.bucket = b
result.Objects = append(result.Objects, &content)
}
for _, commonPrefix := range ret.CommonPrefixes {
obj := &SObject{
bucket: b,
Key: commonPrefix.Prefix,
}
result.CommonPrefixes = append(result.CommonPrefixes, obj)
}
result.IsTruncated = ret.IsTruncated
result.NextMarker = ret.Marker
return result, nil
}
func (region *SRegion) ListBuckets() ([]SBucket, error) {
resp, err := region.bosList("", "/", nil)
if err != nil {
return nil, err
}
buckets := []SBucket{}
err = resp.Unmarshal(&buckets, "buckets")
if err != nil {
return nil, err
}
return buckets, nil
}
func (region *SRegion) CreateBucket(name string, storageClassStr string, aclStr string) error {
_, err := region.bosUpdate(name, "/", nil, nil)
if err != nil {
return err
}
if len(storageClassStr) > 0 {
err = region.SetBucketStorageClass(name, storageClassStr)
if err != nil {
return err
}
}
if len(aclStr) > 0 {
err = region.SetBucketAcl(name, cloudprovider.TBucketACLType(aclStr))
if err != nil {
return err
}
}
return nil
}
func (region *SRegion) DeleteBucket(name string) error {
_, err := region.bosDelete(name, "/", nil)
return err
}
func (region *SRegion) bosList(bucketName, res string, params url.Values) (jsonutils.JSONObject, error) {
return region.client.bosList(region.GetId(), bucketName, res, params)
}
func (region *SRegion) bosDelete(bucketName, res string, params url.Values) (jsonutils.JSONObject, error) {
return region.client.bosDelete(region.GetId(), bucketName, res, params)
}
func (region *SRegion) bosUpdate(bucketName, res string, params url.Values, body map[string]interface{}) (jsonutils.JSONObject, error) {
return region.client.bosUpdate(region.GetId(), bucketName, res, params, body)
}
func (region *SRegion) bosRequest(method httputils.THttpMethod, bucketName, res string, params url.Values, header http.Header, body io.Reader) (*http.Response, error) {
return region.client.bosRequest(method, region.GetId(), bucketName, res, params, header, body)
}
func (region *SRegion) GetBucketStorageClass(bucketName string) (string, error) {
params := url.Values{}
params.Set("storageClass", "")
resp, err := region.bosList(bucketName, "", params)
if err != nil {
return "", err
}
return resp.GetString("storageClass")
}
func (region *SRegion) SetBucketStorageClass(bucketName string, storageClass string) error {
params := url.Values{}
params.Set("storageClass", "")
body := map[string]interface{}{
"storageClass": storageClass,
}
_, err := region.bosUpdate(bucketName, "", params, body)
return err
}
type SAccessControl struct {
AccessControlList []SAccessControlList
Owner struct {
Id string
}
}
func (acl *SAccessControl) GetAcl() cloudprovider.TBucketACLType {
aclType := cloudprovider.ACLUnknown
switch len(acl.AccessControlList) {
case 1:
if acl.AccessControlList[0].Grantee[0].Id == acl.Owner.Id && acl.AccessControlList[0].Permission[0] == "FULL_CONTROL" {
aclType = cloudprovider.ACLPrivate
}
case 2:
isRead, isWrite := false, false
for _, g := range acl.AccessControlList {
if g.Grantee[0].Id == "*" {
for _, permission := range g.Permission {
if strings.EqualFold(permission, "READ") {
isRead = true
}
if strings.EqualFold(permission, "WRITE") {
isWrite = true
}
}
}
}
if isRead && isWrite {
aclType = cloudprovider.ACLPublicReadWrite
} else if isRead {
aclType = cloudprovider.ACLPublicRead
}
}
return aclType
}
type SAccessControlList struct {
Grantee []struct {
Id string
}
Permission []string
}
func (region *SRegion) GetBucketAcl(bucketName string) (*SAccessControl, error) {
params := url.Values{}
params.Set("acl", "")
resp, err := region.bosList(bucketName, "", params)
if err != nil {
return nil, err
}
ret := &SAccessControl{}
err = resp.Unmarshal(ret)
if err != nil {
return nil, err
}
return ret, nil
}
func (region *SRegion) SetBucketAcl(bucketName string, acl cloudprovider.TBucketACLType) error {
params := url.Values{}
params.Set("acl", "")
header := http.Header{}
header.Set("x-bce-acl", string(acl))
resp, err := region.bosRequest(httputils.PUT, bucketName, "", params, header, nil)
if err != nil {
return errors.Wrapf(err, "SetBucketAcl %s %s", bucketName, acl)
}
httputils.CloseResponse(resp)
return nil
}
+86
View File
@@ -0,0 +1,86 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package baidu
import (
"context"
"net/http"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
)
type SObject struct {
cloudprovider.SBaseCloudObject
bucket *SBucket
Key string
LastModified time.Time
ETag string
Size int64
StorageClass string
Owner struct {
Id string
DisplayName string
}
}
func (o *SObject) GetKey() string {
return o.Key
}
func (o *SObject) GetSizeBytes() int64 {
return o.Size
}
func (o *SObject) GetLastModified() time.Time {
return o.LastModified
}
func (o *SObject) GetStorageClass() string {
return o.StorageClass
}
func (o *SObject) GetETag() string {
return o.ETag
}
func (o *SObject) GetOwner() struct {
Id string
DisplayName string
} {
return o.Owner
}
func (o *SObject) GetAcl() cloudprovider.TBucketACLType {
return cloudprovider.ACLPrivate
}
func (o *SObject) SetAcl(acl cloudprovider.TBucketACLType) error {
return o.bucket.SetAcl(acl)
}
func (o *SObject) GetMeta() http.Header {
return o.Meta
}
func (o *SObject) SetMeta(ctx context.Context, meta http.Header) error {
return cloudprovider.ErrNotImplemented
}
func (o *SObject) GetIBucket() cloudprovider.ICloudBucket {
return o.bucket
}
+3 -1
View File
@@ -167,7 +167,9 @@ func (self *SBaiduProvider) CreateIProject(name string) (cloudprovider.ICloudPro
}
func (self *SBaiduProvider) GetStorageClasses(regionId string) []string {
return []string{}
return []string{
"STANDARD", "STANDARD_IA", "COLD", "ARCHIVE",
}
}
func (self *SBaiduProvider) GetBucketCannedAcls(regionId string) []string {
+54
View File
@@ -344,3 +344,57 @@ func (region *SRegion) eipDelete(resource string, params url.Values) (jsonutils.
func (region *SRegion) eipUpdate(resource string, params url.Values, body map[string]interface{}) (jsonutils.JSONObject, error) {
return region.client.eipUpdate(region.RegionId, resource, params, body)
}
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
buckets, err := region.ListBuckets()
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudBucket{}
for i := range buckets {
if buckets[i].Location != region.GetId() {
continue
}
buckets[i].region = region
ret = append(ret, &buckets[i])
}
return ret, nil
}
func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
return region.CreateBucket(name, storageClassStr, aclStr)
}
func (region *SRegion) DeleteIBucket(name string) error {
return region.DeleteBucket(name)
}
func (region *SRegion) IBucketExist(name string) (bool, error) {
buckets, err := region.GetIBuckets()
if err != nil {
return false, errors.Wrapf(err, "GetIBuckets")
}
for i := range buckets {
if buckets[i].GetName() == name {
return true, nil
}
}
return false, nil
}
func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) {
buckets, err := region.GetIBuckets()
if err != nil {
return nil, errors.Wrapf(err, "GetIBuckets")
}
for i := range buckets {
if buckets[i].GetName() == name {
return buckets[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
return region.GetIBucketById(name)
}
+10 -6
View File
@@ -101,22 +101,26 @@ func getCanonicalHeaders(headers http.Header,
return strings.Join(canonicalHeaders, "\n"), signHeaders
}
func (cli *SBaiduClient) sign(req *http.Request) (string, error) {
func (cli *SBaiduClient) sign(uri *url.URL, method string, headers http.Header) (string, error) {
return cli._sign(uri, method, headers, 1800)
}
func (cli *SBaiduClient) _sign(uri *url.URL, method string, headers http.Header, expired int) (string, error) {
signKeyInfo := fmt.Sprintf("%s/%s/%s/%d",
"bce-auth-v1",
cli.accessKeyId,
time.Now().UTC().Format(ISO8601),
1800)
expired)
hasher := hmac.New(sha256.New, []byte(cli.accessKeySecret))
hasher.Write([]byte(signKeyInfo))
signKey := hex.EncodeToString(hasher.Sum(nil))
canonicalUri := getCanonicalURIPath(req.URL.Path)
params, err := url.ParseQuery(req.URL.RawQuery)
canonicalUri := getCanonicalURIPath(uri.Path)
params, err := url.ParseQuery(uri.RawQuery)
if err != nil {
return "", errors.Wrapf(err, "ParseQuery")
}
canonicalQueryString := getCanonicalQueryString(params)
canonicalHeaders, signedHeadersArr := getCanonicalHeaders(req.Header, map[string]bool{
canonicalHeaders, signedHeadersArr := getCanonicalHeaders(headers, map[string]bool{
"host": true,
"Content-Length": true,
"Content-Type": true,
@@ -129,7 +133,7 @@ func (cli *SBaiduClient) sign(req *http.Request) (string, error) {
signedHeaders = strings.Join(signedHeadersArr, ";")
}
canonicalParts := []string{req.Method, canonicalUri, canonicalQueryString, canonicalHeaders}
canonicalParts := []string{method, canonicalUri, canonicalQueryString, canonicalHeaders}
canonicalReq := strings.Join(canonicalParts, "\n")
hasher = hmac.New(sha256.New, []byte(signKey))
hasher.Write([]byte(canonicalReq))
+7 -6
View File
@@ -111,13 +111,14 @@ func (cli *SGoogleClient) GetGlobalNetworks(maxResults int, pageToken string) ([
if err != nil {
return nil, errors.Wrap(err, "ecsList")
}
if resp.Contains("items") {
err = resp.Unmarshal(&networks, "items")
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
}
ret := struct {
Items []SGlobalNetwork
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
}
return networks, nil
return ret.Items, nil
}
func (self *SGoogleClient) CreateGlobalNetwork(name string, desc string) (*SGlobalNetwork, error) {
+5 -3
View File
@@ -76,12 +76,14 @@ func (self *SGoogleClient) TestIam(permissions []string) ([]string, error) {
if err != nil {
return nil, errors.Wrap(err, "testIamPermissions")
}
ret := []string{}
err = resp.Unmarshal(&ret, "permissions")
ret := struct {
Permissions []string
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
}
return ret, nil
return ret.Permissions, nil
}
func (self *SGoogleClient) IsSupportCloudId() bool {
+8 -8
View File
@@ -58,16 +58,16 @@ func (cli *SGoogleClient) GetProjects() ([]SProject, error) {
if err != nil {
return nil, errors.Wrap(err, "managerList")
}
_result := []SProject{}
if resp.Contains("projects") {
err = resp.Unmarshal(&_result, "projects")
if err != nil {
return nil, errors.Wrap(err, "data.Unmarshal")
}
part := struct {
Projects []SProject
}{}
err = resp.Unmarshal(&part)
if err != nil {
return nil, errors.Wrapf(err, "resp.Unmarshal")
}
result = append(result, _result...)
result = append(result, part.Projects...)
nextPageToken, _ = resp.GetString("nextPageToken")
if len(nextPageToken) == 0 || len(_result) == 0 {
if len(nextPageToken) == 0 || len(part.Projects) == 0 {
break
}
}
+6 -4
View File
@@ -46,10 +46,12 @@ func (self *SGoogleClient) ListOrganizations() ([]SOrganization, error) {
return nil, errors.Wrap(err, "ListOrganizations")
}
log.Debugf("ListOrganization: %s", resp)
ret := make([]SOrganization, 0)
err = resp.Unmarshal(&ret, "organizations")
ret := struct {
Organizations []SOrganization
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
return nil, errors.Wrapf(err, "resp.Unmarshal")
}
return ret, nil
return ret.Organizations, nil
}
+4 -3
View File
@@ -7,6 +7,7 @@ import (
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/pkg/errors"
)
type SSharedGlobalNetwork struct {
@@ -72,20 +73,20 @@ func (client *SGoogleClient) GetSharedGlobalNetworks() ([]SSharedGlobalNetwork,
if e, ok := err.(*gError); ok && e.ErrorInfo.Code == 400 {
return []SSharedGlobalNetwork{}, nil
}
return nil, err
return nil, errors.Wrapf(err, "GetXpnHosts")
}
ret := []SSharedGlobalNetwork{}
networkMap := map[string][]SXpnNetwork{}
for _, xhost := range xhosts {
resources, err := client.GetXpnResources(xhost.Name)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "GetXpnResources(%s)", xhost.Name)
}
for _, resource := range resources {
if strings.EqualFold(resource.Type, "project") && resource.Id == client.projectId {
networks, err := client.GetXpnNetworks(xhost.Name)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "GetXpnNetworks(%s)", xhost.Name)
}
for i := range networks {
_, ok := networkMap[networks[i].Network]
+10 -6
View File
@@ -13,12 +13,14 @@ func (cli *SGoogleClient) GetXpnHosts() ([]SXpnHost, error) {
if err != nil {
return nil, err
}
ret := []SXpnHost{}
err = resp.Unmarshal(&ret, "items")
ret := struct {
Items []SXpnHost
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, err
}
return ret, nil
return ret.Items, nil
}
type SXpnResource struct {
@@ -32,10 +34,12 @@ func (cli *SGoogleClient) GetXpnResources(projectId string) ([]SXpnResource, err
if err != nil {
return nil, err
}
ret := []SXpnResource{}
err = resp.Unmarshal(&ret, "resources")
ret := struct {
Resources []SXpnResource
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, err
}
return ret, nil
return ret.Resources, nil
}
+5 -3
View File
@@ -108,10 +108,12 @@ func (client *SGoogleClient) GetXpnNetworks(projectId string) ([]SXpnNetwork, er
if err != nil {
return nil, err
}
ret := []SXpnNetwork{}
err = resp.Unmarshal(&ret, "items")
ret := struct {
Items []SXpnNetwork
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, err
}
return ret, nil
return ret.Items, nil
}