| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011 |
- // 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 aliyun
- import (
- "context"
- "fmt"
- "io"
- "net/http"
- "strconv"
- "strings"
- "time"
- "github.com/aliyun/aliyun-oss-go-sdk/oss"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/utils"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/cloudmux/pkg/multicloud"
- )
- type SBucket struct {
- multicloud.SBaseBucket
- AliyunTags
- region *SRegion
- Name string
- Location string
- CreationDate time.Time
- StorageClass string
- }
- func (b *SBucket) GetProjectId() string {
- return ""
- }
- func (b *SBucket) GetGlobalId() string {
- return b.Name
- }
- func (b *SBucket) GetName() string {
- return b.Name
- }
- func (b *SBucket) GetAcl() cloudprovider.TBucketACLType {
- acl := cloudprovider.ACLPrivate
- osscli, err := b.getOssClient()
- if err != nil {
- log.Errorf("b.region.GetOssClient fail %s", err)
- return acl
- }
- aclResp, err := osscli.GetBucketACL(b.Name)
- if err != nil {
- log.Errorf("osscli.GetBucketACL fail %s", err)
- return acl
- }
- acl = cloudprovider.TBucketACLType(aclResp.ACL)
- return acl
- }
- func (b *SBucket) GetLocation() string {
- return b.Location
- }
- func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
- return b.region
- }
- func (b *SBucket) GetCreatedAt() time.Time {
- return b.CreationDate
- }
- func (b *SBucket) GetStorageClass() string {
- return b.StorageClass
- }
- func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
- ret := []cloudprovider.SBucketAccessUrl{
- {
- Url: fmt.Sprintf("%s.%s", b.Name, b.region.getOSSExternalDomain()),
- Description: "ExtranetEndpoint",
- Primary: true,
- },
- {
- Url: fmt.Sprintf("%s.%s", b.Name, b.region.getOSSInternalDomain()),
- Description: "IntranetEndpoint",
- },
- }
- return ret
- }
- func (b *SBucket) GetStats() cloudprovider.SBucketStats {
- stats, err := cloudprovider.GetIBucketStats(b)
- if err != nil {
- log.Errorf("GetStats fail %s", err)
- }
- return stats
- }
- func (b *SBucket) SetAcl(aclStr cloudprovider.TBucketACLType) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- log.Errorf("b.region.GetOssClient fail %s", err)
- return errors.Wrap(err, "b.region.GetOssClient")
- }
- acl, err := str2Acl(string(aclStr))
- if err != nil {
- return errors.Wrap(err, "str2Acl")
- }
- err = osscli.SetBucketACL(b.Name, acl)
- if err != nil {
- return errors.Wrap(err, "SetBucketACL")
- }
- return nil
- }
- func (b *SBucket) getOssClient() (*oss.Client, error) {
- if b.region.client.GetAccessEnv() == ALIYUN_FINANCE_CLOUDENV {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrapf(err, "GetOssClient")
- }
- info, err := osscli.GetBucketInfo(b.Name)
- if err != nil {
- return nil, errors.Wrapf(err, "GetBucketInfo")
- }
- if len(info.BucketInfo.ExtranetEndpoint) > 0 {
- return b.region.client.getOssClientByEndpoint(info.BucketInfo.ExtranetEndpoint)
- }
- }
- return b.region.GetOssClient()
- }
- func (b *SBucket) ListObjects(prefix string, marker string, delimiter string, maxCount int) (cloudprovider.SListObjectResult, error) {
- result := cloudprovider.SListObjectResult{}
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return result, errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return result, errors.Wrap(err, "Bucket")
- }
- opts := make([]oss.Option, 0)
- if len(prefix) > 0 {
- opts = append(opts, oss.Prefix(prefix))
- }
- if len(delimiter) > 0 {
- opts = append(opts, oss.Delimiter(delimiter))
- }
- if len(marker) > 0 {
- opts = append(opts, oss.Marker(marker))
- }
- if maxCount > 0 {
- opts = append(opts, oss.MaxKeys(maxCount))
- }
- oResult, err := bucket.ListObjects(opts...)
- if err != nil {
- return result, errors.Wrap(err, "ListObjects")
- }
- result.Objects = make([]cloudprovider.ICloudObject, 0)
- for _, object := range oResult.Objects {
- obj := &SObject{
- bucket: b,
- SBaseCloudObject: cloudprovider.SBaseCloudObject{
- StorageClass: object.StorageClass,
- Key: object.Key,
- SizeBytes: object.Size,
- ETag: object.ETag,
- LastModified: object.LastModified,
- },
- }
- result.Objects = append(result.Objects, obj)
- }
- if oResult.CommonPrefixes != nil {
- result.CommonPrefixes = make([]cloudprovider.ICloudObject, len(oResult.CommonPrefixes))
- for i, commPrefix := range oResult.CommonPrefixes {
- result.CommonPrefixes[i] = &SObject{
- bucket: b,
- SBaseCloudObject: cloudprovider.SBaseCloudObject{Key: commPrefix},
- }
- }
- }
- result.IsTruncated = oResult.IsTruncated
- result.NextMarker = oResult.NextMarker
- return result, nil
- }
- func metaOpts(opts []oss.Option, meta http.Header) []oss.Option {
- for k, v := range meta {
- if len(v) == 0 {
- continue
- }
- switch http.CanonicalHeaderKey(k) {
- case cloudprovider.META_HEADER_CONTENT_TYPE:
- opts = append(opts, oss.ContentType(v[0]))
- case cloudprovider.META_HEADER_CONTENT_MD5:
- opts = append(opts, oss.ContentMD5(v[0]))
- case cloudprovider.META_HEADER_CONTENT_LANGUAGE:
- opts = append(opts, oss.ContentLanguage(v[0]))
- case cloudprovider.META_HEADER_CONTENT_ENCODING:
- opts = append(opts, oss.ContentEncoding(v[0]))
- case cloudprovider.META_HEADER_CONTENT_DISPOSITION:
- opts = append(opts, oss.ContentDisposition(v[0]))
- case cloudprovider.META_HEADER_CACHE_CONTROL:
- opts = append(opts, oss.CacheControl(v[0]))
- default:
- opts = append(opts, oss.Meta(http.CanonicalHeaderKey(k), v[0]))
- }
- }
- return opts
- }
- func (b *SBucket) PutObject(ctx context.Context, key string, input io.Reader, sizeBytes int64, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return errors.Wrap(err, "Bucket")
- }
- opts := make([]oss.Option, 0)
- if sizeBytes > 0 {
- opts = append(opts, oss.ContentLength(sizeBytes))
- }
- if meta != nil {
- opts = metaOpts(opts, meta)
- }
- if len(cannedAcl) == 0 {
- cannedAcl = b.GetAcl()
- }
- acl, err := str2Acl(string(cannedAcl))
- if err != nil {
- return errors.Wrap(err, "")
- }
- opts = append(opts, oss.ObjectACL(acl))
- if len(storageClassStr) > 0 {
- storageClass, err := str2StorageClass(storageClassStr)
- if err != nil {
- return errors.Wrap(err, "str2StorageClass")
- }
- opts = append(opts, oss.ObjectStorageClass(storageClass))
- }
- return bucket.PutObject(key, input, opts...)
- }
- func (b *SBucket) NewMultipartUpload(ctx context.Context, key string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) (string, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return "", errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return "", errors.Wrap(err, "Bucket")
- }
- opts := make([]oss.Option, 0)
- if meta != nil {
- opts = metaOpts(opts, meta)
- }
- if len(cannedAcl) == 0 {
- cannedAcl = b.GetAcl()
- }
- acl, err := str2Acl(string(cannedAcl))
- if err != nil {
- return "", errors.Wrap(err, "str2Acl")
- }
- opts = append(opts, oss.ObjectACL(acl))
- if len(storageClassStr) > 0 {
- storageClass, err := str2StorageClass(storageClassStr)
- if err != nil {
- return "", errors.Wrap(err, "str2StorageClass")
- }
- opts = append(opts, oss.ObjectStorageClass(storageClass))
- }
- result, err := bucket.InitiateMultipartUpload(key, opts...)
- if err != nil {
- return "", errors.Wrap(err, "bucket.InitiateMultipartUpload")
- }
- return result.UploadID, nil
- }
- func (b *SBucket) UploadPart(ctx context.Context, key string, uploadId string, partIndex int, input io.Reader, partSize int64, offset, totalSize int64) (string, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return "", errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return "", errors.Wrap(err, "Bucket")
- }
- imur := oss.InitiateMultipartUploadResult{
- Bucket: b.Name,
- Key: key,
- UploadID: uploadId,
- }
- part, err := bucket.UploadPart(imur, input, partSize, partIndex)
- if err != nil {
- return "", errors.Wrap(err, "bucket.UploadPart")
- }
- if b.region.client.debug {
- log.Debugf("upload part key:%s uploadId:%s partIndex:%d etag:%s", key, uploadId, partIndex, part.ETag)
- }
- return part.ETag, nil
- }
- func (b *SBucket) CompleteMultipartUpload(ctx context.Context, key string, uploadId string, partEtags []string) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return errors.Wrap(err, "Bucket")
- }
- imur := oss.InitiateMultipartUploadResult{
- Bucket: b.Name,
- Key: key,
- UploadID: uploadId,
- }
- parts := make([]oss.UploadPart, len(partEtags))
- for i := range partEtags {
- parts[i] = oss.UploadPart{
- PartNumber: i + 1,
- ETag: partEtags[i],
- }
- }
- result, err := bucket.CompleteMultipartUpload(imur, parts)
- if err != nil {
- return errors.Wrap(err, "bucket.CompleteMultipartUpload")
- }
- if b.region.client.debug {
- log.Debugf("CompleteMultipartUpload bucket:%s key:%s etag:%s location:%s", result.Bucket, result.Key, result.ETag, result.Location)
- }
- return nil
- }
- func (b *SBucket) AbortMultipartUpload(ctx context.Context, key string, uploadId string) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return errors.Wrap(err, "Bucket")
- }
- imur := oss.InitiateMultipartUploadResult{
- Bucket: b.Name,
- Key: key,
- UploadID: uploadId,
- }
- err = bucket.AbortMultipartUpload(imur)
- if err != nil {
- return errors.Wrap(err, "AbortMultipartUpload")
- }
- return nil
- }
- func (b *SBucket) DeleteObject(ctx context.Context, key string) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return errors.Wrap(err, "Bucket")
- }
- err = bucket.DeleteObject(key)
- if err != nil {
- return errors.Wrap(err, "DeleteObject")
- }
- return nil
- }
- func (b *SBucket) GetTempUrl(method string, key string, expire time.Duration) (string, error) {
- if method != "GET" && method != "PUT" && method != "DELETE" {
- return "", errors.Error("unsupported method")
- }
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return "", errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return "", errors.Wrap(err, "Bucket")
- }
- urlStr, err := bucket.SignURL(key, oss.HTTPMethod(method), int64(expire/time.Second))
- if err != nil {
- return "", errors.Wrap(err, "SignURL")
- }
- return urlStr, nil
- }
- func (b *SBucket) CopyObject(ctx context.Context, destKey string, srcBucket, srcKey string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return errors.Wrap(err, "Bucket")
- }
- opts := make([]oss.Option, 0)
- if meta != nil {
- opts = metaOpts(opts, meta)
- }
- if len(cannedAcl) == 0 {
- cannedAcl = b.GetAcl()
- }
- acl, err := str2Acl(string(cannedAcl))
- if err != nil {
- return errors.Wrap(err, "str2Acl")
- }
- opts = append(opts, oss.ObjectACL(acl))
- if len(storageClassStr) > 0 {
- storageClass, err := str2StorageClass(storageClassStr)
- if err != nil {
- return errors.Wrap(err, "str2StorageClass")
- }
- opts = append(opts, oss.ObjectStorageClass(storageClass))
- }
- _, err = bucket.CopyObjectFrom(srcBucket, srcKey, destKey, opts...)
- if err != nil {
- return errors.Wrap(err, "CopyObjectFrom")
- }
- return nil
- }
- func (b *SBucket) GetObject(ctx context.Context, key string, rangeOpt *cloudprovider.SGetObjectRange) (io.ReadCloser, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return nil, errors.Wrap(err, "Bucket")
- }
- opts := make([]oss.Option, 0)
- if rangeOpt != nil {
- opts = append(opts, oss.NormalizedRange(rangeOpt.String()))
- }
- output, err := bucket.GetObject(key, opts...)
- if err != nil {
- return nil, errors.Wrap(err, "bucket.GetObject")
- }
- return output, nil
- }
- func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, partNumber int, srcBucket string, srcKey string, srcOffset int64, srcLength int64) (string, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return "", errors.Wrap(err, "GetOssClient")
- }
- bucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return "", errors.Wrap(err, "Bucket")
- }
- imur := oss.InitiateMultipartUploadResult{
- Bucket: b.Name,
- Key: key,
- UploadID: uploadId,
- }
- opts := make([]oss.Option, 0)
- part, err := bucket.UploadPartCopy(imur, srcBucket, srcKey, srcOffset, srcLength, partNumber, opts...)
- if err != nil {
- return "", errors.Wrap(err, "bucket.UploadPartCopy")
- }
- return part.ETag, nil
- }
- func (b *SBucket) SetWebsite(websitConf cloudprovider.SBucketWebsiteConf) error {
- if len(websitConf.Index) == 0 {
- return errors.Wrap(cloudprovider.ErrNotSupported, "missing Index")
- }
- if len(websitConf.ErrorDocument) == 0 {
- return errors.Wrap(cloudprovider.ErrNotSupported, "missing ErrorDocument")
- }
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- err = osscli.SetBucketWebsite(b.Name, websitConf.Index, websitConf.ErrorDocument)
- if err != nil {
- return errors.Wrapf(err, " osscli.SetBucketWebsite(%s,%s,%s)", b.Name, websitConf.Index, websitConf.ErrorDocument)
- }
- return nil
- }
- func (b *SBucket) GetWebsiteConf() (cloudprovider.SBucketWebsiteConf, error) {
- result := cloudprovider.SBucketWebsiteConf{}
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return result, errors.Wrap(err, "GetOssClient")
- }
- websiteResult, err := osscli.GetBucketWebsite(b.Name)
- if err != nil {
- if strings.Contains(err.Error(), "NoSuchWebsiteConfiguration") {
- return cloudprovider.SBucketWebsiteConf{}, nil
- }
- return result, errors.Wrapf(err, "osscli.GetBucketWebsite(%s)", b.Name)
- }
- result.Index = websiteResult.IndexDocument.Suffix
- result.ErrorDocument = websiteResult.ErrorDocument.Key
- return result, nil
- }
- func (b *SBucket) DeleteWebSiteConf() error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- log.Infof("to be delete")
- err = osscli.DeleteBucketWebsite(b.Name)
- if err != nil {
- return errors.Wrapf(err, "osscli.DeleteBucketWebsite(%s)", b.Name)
- }
- log.Infof("deleted")
- return nil
- }
- func (b *SBucket) SetCORS(rules []cloudprovider.SBucketCORSRule) error {
- if len(rules) == 0 {
- return nil
- }
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- input := []oss.CORSRule{}
- for i := range rules {
- input = append(input, oss.CORSRule{
- AllowedOrigin: rules[i].AllowedOrigins,
- AllowedMethod: rules[i].AllowedMethods,
- AllowedHeader: rules[i].AllowedHeaders,
- MaxAgeSeconds: rules[i].MaxAgeSeconds,
- ExposeHeader: rules[i].ExposeHeaders,
- })
- }
- err = osscli.SetBucketCORS(b.Name, input)
- if err != nil {
- return errors.Wrapf(err, "osscli.SetBucketCORS(%s,%s)", b.Name, jsonutils.Marshal(input).String())
- }
- return nil
- }
- func (b *SBucket) GetCORSRules() ([]cloudprovider.SBucketCORSRule, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "GetOssClient")
- }
- conf, err := osscli.GetBucketCORS(b.Name)
- if err != nil {
- if !strings.Contains(err.Error(), "NoSuchCORSConfiguration") {
- return nil, errors.Wrapf(err, "osscli.GetBucketCORS(%s)", b.Name)
- }
- }
- result := []cloudprovider.SBucketCORSRule{}
- for i := range conf.CORSRules {
- result = append(result, cloudprovider.SBucketCORSRule{
- AllowedOrigins: conf.CORSRules[i].AllowedOrigin,
- AllowedMethods: conf.CORSRules[i].AllowedMethod,
- AllowedHeaders: conf.CORSRules[i].AllowedHeader,
- MaxAgeSeconds: conf.CORSRules[i].MaxAgeSeconds,
- ExposeHeaders: conf.CORSRules[i].ExposeHeader,
- Id: strconv.Itoa(i),
- })
- }
- return result, nil
- }
- func (b *SBucket) DeleteCORS() error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- err = osscli.DeleteBucketCORS(b.Name)
- if err != nil {
- return errors.Wrapf(err, "osscli.DeleteBucketCORS(%s)", b.Name)
- }
- return nil
- }
- func (b *SBucket) SetReferer(conf cloudprovider.SBucketRefererConf) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- if !conf.Enabled {
- return errors.Wrapf(cloudprovider.ErrNotSupported, "Disable Refer")
- }
- if conf.RefererType == "Black-List" {
- return errors.Wrapf(cloudprovider.ErrNotSupported, "Black List")
- }
- err = osscli.SetBucketReferer(b.Name, conf.DomainList, conf.AllowEmptyRefer)
- if err != nil {
- return errors.Wrapf(err, "osscli.SetBucketReferer(%s,%s,%t)", b.Name, conf.DomainList, conf.AllowEmptyRefer)
- }
- return nil
- }
- func (b *SBucket) GetReferer() (cloudprovider.SBucketRefererConf, error) {
- result := cloudprovider.SBucketRefererConf{}
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return result, errors.Wrap(err, "GetOssClient")
- }
- refererResult, err := osscli.GetBucketReferer(b.Name)
- if err != nil {
- return result, errors.Wrapf(err, "osscli.GetBucketReferer(%s)", b.Name)
- }
- result = cloudprovider.SBucketRefererConf{
- Enabled: true,
- RefererType: "White-List",
- DomainList: refererResult.RefererList,
- AllowEmptyRefer: refererResult.AllowEmptyReferer,
- }
- return result, nil
- }
- func toAPICdnArea(area string) string {
- switch area {
- case "domestic":
- return api.CDN_DOMAIN_AREA_MAINLAND
- case "overseas":
- return api.CDN_DOMAIN_AREA_OVERSEAS
- case "global":
- return api.CDN_DOMAIN_AREA_GLOBAL
- default:
- return ""
- }
- }
- func toAPICdnStatus(status string) string {
- switch status {
- case "online":
- return api.CDN_DOMAIN_STATUS_ONLINE
- case "offline":
- return api.CDN_DOMAIN_STATUS_OFFLINE
- case "configuring", "checking", "stopping", "deleting":
- return api.CDN_DOMAIN_STATUS_PROCESSING
- case "check_failed", "configure_failed":
- return api.CDN_DOMAIN_STATUS_REJECTED
- default:
- return ""
- }
- }
- func (b *SBucket) GetCdnDomains() ([]cloudprovider.SCdnDomain, error) {
- bucketExtUrl := fmt.Sprintf("%s.%s", b.Name, b.region.getOSSExternalDomain())
- cdnDomains, err := b.region.client.DescribeDomainsBySource(bucketExtUrl)
- if err != nil {
- return nil, errors.Wrapf(err, " b.region.client.DescribeDomainsBySource(%s)", bucketExtUrl)
- }
- result := []cloudprovider.SCdnDomain{}
- for i := range cdnDomains.DomainsData {
- if cdnDomains.DomainsData[i].Source == bucketExtUrl {
- for j := range cdnDomains.DomainsData[i].Domains.DomainNames {
- area := ""
- domain, _ := b.region.client.GetCDNDomainByName(cdnDomains.DomainsData[i].Domains.DomainNames[j])
- if domain != nil {
- area = domain.Coverage
- }
- result = append(result, cloudprovider.SCdnDomain{
- Domain: cdnDomains.DomainsData[i].Domains.DomainNames[j],
- Status: toAPICdnStatus(cdnDomains.DomainsData[i].DomainInfos.DomainInfo[j].Status),
- Cname: cdnDomains.DomainsData[i].DomainInfos.DomainInfo[j].DomainCname,
- Area: toAPICdnArea(area),
- Origin: bucketExtUrl,
- OriginType: api.CDN_DOMAIN_ORIGIN_TYPE_BUCKET,
- })
- }
- }
- }
- return result, nil
- }
- func (b *SBucket) GetTags() (map[string]string, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "GetOssClient")
- }
- tagresult, err := osscli.GetBucketTagging(b.Name)
- if err != nil {
- return nil, errors.Wrapf(err, "GetBucketTagging %s", b.Name)
- }
- result := map[string]string{}
- for _, tag := range tagresult.Tags {
- result[tag.Key] = tag.Value
- }
- return result, nil
- }
- func (b *SBucket) SetTags(tags map[string]string, replace bool) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- err = osscli.DeleteBucketTagging(b.Name)
- if err != nil {
- return errors.Wrapf(err, "DeleteBucketTagging(%s)", b.Name)
- }
- if len(tags) == 0 {
- return nil
- }
- input := []oss.Tag{}
- for k, v := range tags {
- input = append(input, oss.Tag{Key: k, Value: v})
- }
- err = osscli.SetBucketTagging(b.Name, oss.Tagging{Tags: input})
- if err != nil {
- return errors.Wrapf(err, "osscli.SetBucketTagging(%s)", jsonutils.Marshal(input))
- }
- return nil
- }
- func (b *SBucket) ListMultipartUploads() ([]cloudprovider.SBucketMultipartUploads, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "GetOssClient")
- }
- result := []cloudprovider.SBucketMultipartUploads{}
- ossBucket, err := osscli.Bucket(b.Name)
- if err != nil {
- return nil, errors.Wrap(err, "osscli.Bucket(b.Name)")
- }
- keyMarker := oss.KeyMarker("")
- uploadIDMarker := oss.UploadIDMarker("")
- for {
- output, err := ossBucket.ListMultipartUploads(keyMarker, uploadIDMarker)
- if err != nil {
- return nil, errors.Wrap(err, " coscli.Bucket.ListMultipartUploads(context.Background(), &input)")
- }
- for i := range output.Uploads {
- temp := cloudprovider.SBucketMultipartUploads{
- ObjectName: output.Uploads[i].Key,
- UploadID: output.Uploads[i].UploadID,
- Initiated: output.Uploads[i].Initiated,
- }
- result = append(result, temp)
- }
- keyMarker = oss.KeyMarker(output.NextKeyMarker)
- uploadIDMarker = oss.UploadIDMarker(output.NextUploadIDMarker)
- if !output.IsTruncated {
- break
- }
- }
- return result, nil
- }
- type SBucketPolicyStatement struct {
- Version string `json:"Version"`
- Statement []SBucketPolicyStatementDetails `json:"Statement"`
- }
- type SBucketPolicyStatementDetails struct {
- Action []string `json:"Action"`
- Effect string `json:"Effect"`
- Principal []string `json:"Principal"`
- Resource []string `json:"Resource"`
- Condition map[string]map[string]interface{} `json:"Condition"`
- }
- func (b *SBucket) GetPolicy() ([]cloudprovider.SBucketPolicyStatement, error) {
- policies, err := b.getPolicy()
- if err != nil {
- if errors.Cause(err) == errors.ErrNotFound {
- return []cloudprovider.SBucketPolicyStatement{}, nil
- }
- return nil, errors.Wrap(err, "getPolicy")
- }
- return b.localPolicyToCloudprovider(policies), nil
- }
- func (b *SBucket) getPolicy() ([]SBucketPolicyStatementDetails, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "GetOssClient")
- }
- policies := []SBucketPolicyStatementDetails{}
- resStr, err := osscli.GetBucketPolicy(b.Name)
- if err != nil {
- if strings.Contains(err.Error(), "NoSuchBucketPolicy") {
- return policies, nil
- }
- return nil, errors.Wrap(err, "GetBucketPolicy")
- }
- obj, err := jsonutils.Parse([]byte(resStr))
- if err != nil {
- return nil, errors.Wrap(err, "Parse resStr")
- }
- return policies, obj.Unmarshal(&policies, "Statement")
- }
- func (b *SBucket) SetPolicy(policy cloudprovider.SBucketPolicyStatementInput) error {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "GetOssClient")
- }
- policies, err := b.getPolicy()
- if err != nil {
- return errors.Wrap(err, "getPolicy")
- }
- param := SBucketPolicyStatement{}
- param.Version = "1"
- param.Statement = policies
- resources := []string{}
- for i := range policy.ResourcePath {
- resources = append(resources, fmt.Sprintf("acs:oss:*:%s:%s%s", b.region.client.GetAccountId(), b.Name, policy.ResourcePath[i]))
- }
- ids := []string{}
- for i := range policy.PrincipalId {
- id := strings.Split(policy.PrincipalId[i], ":")
- if len(id) == 1 {
- ids = append(ids, "*")
- }
- if len(id) == 2 {
- // 没有子账号,默认和主账号相同
- if len(id[1]) == 0 {
- id[1] = "*"
- }
- ids = append(ids, id[1])
- }
- if len(id) > 2 {
- return errors.Wrap(cloudprovider.ErrNotSupported, "Invalida PrincipalId Input")
- }
- }
- param.Statement = append(param.Statement, SBucketPolicyStatementDetails{
- Resource: resources,
- // Principal: policy.PrincipalId,
- Principal: ids,
- Effect: policy.Effect,
- Condition: policy.Condition,
- Action: b.cannedActionToAction(policy.CannedAction),
- })
- err = osscli.SetBucketPolicy(b.Name, jsonutils.Marshal(param).String())
- if err != nil {
- return errors.Wrap(err, "SetBucketPolicy")
- }
- return nil
- }
- func (b *SBucket) DeletePolicy(id []string) ([]cloudprovider.SBucketPolicyStatement, error) {
- osscli, err := b.region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "GetOssClient")
- }
- param := SBucketPolicyStatement{}
- param.Version = "1"
- param.Statement = []SBucketPolicyStatementDetails{}
- policies, err := b.getPolicy()
- if err != nil {
- return nil, errors.Wrap(err, "getPolicy")
- }
- for i, policy := range policies {
- if utils.IsInStringArray(fmt.Sprintf("%d", i), id) {
- continue
- }
- param.Statement = append(param.Statement, policy)
- }
- err = osscli.DeleteBucketPolicy(b.Name)
- if err != nil {
- return nil, errors.Wrap(err, "DeleteBucketPolicy")
- }
- if len(param.Statement) > 0 {
- err = osscli.SetBucketPolicy(b.Name, jsonutils.Marshal(param).String())
- if err != nil {
- return nil, errors.Wrap(err, "SetBucketPolicy")
- }
- }
- return b.localPolicyToCloudprovider(param.Statement), nil
- }
- func (b *SBucket) localPolicyToCloudprovider(policies []SBucketPolicyStatementDetails) []cloudprovider.SBucketPolicyStatement {
- res := []cloudprovider.SBucketPolicyStatement{}
- for i, policy := range policies {
- res = append(res, cloudprovider.SBucketPolicyStatement{
- Principal: map[string][]string{"acs": policy.Principal},
- PrincipalId: getLocalPrincipalId(policy.Principal),
- Action: policy.Action,
- Effect: policy.Effect,
- Resource: b.getResourcePaths(policy.Resource),
- ResourcePath: b.getResourcePaths(policy.Resource),
- Condition: policy.Condition,
- CannedAction: b.actionToCannedAction(policy.Action),
- Id: fmt.Sprintf("%d", i),
- })
- }
- return res
- }
- var readActions = []string{
- "oss:GetObject",
- "oss:GetObjectAcl",
- "oss:ListObjects",
- "oss:RestoreObject",
- "oss:GetVodPlaylist",
- "oss:ListObjectVersions",
- "oss:GetObjectVersion",
- "oss:GetObjectVersionAcl",
- "oss:RestoreObjectVersion",
- }
- var readWriteActions = []string{
- "oss:GetObject",
- "oss:PutObject",
- "oss:GetObjectAcl",
- "oss:PutObjectAcl",
- "oss:ListObjects",
- "oss:AbortMultipartUpload",
- "oss:ListParts",
- "oss:RestoreObject",
- "oss:GetVodPlaylist",
- "oss:PostVodPlaylist",
- "oss:PublishRtmpStream",
- "oss:ListObjectVersions",
- "oss:GetObjectVersion",
- "oss:GetObjectVersionAcl",
- "oss:RestoreObjectVersion",
- }
- var fullControlActions = []string{"oss:*"}
- func (b *SBucket) cannedActionToAction(s string) []string {
- switch s {
- case "Read":
- return readActions
- case "ReadWrite":
- return readWriteActions
- case "FullControl":
- return fullControlActions
- default:
- return nil
- }
- }
- func (b *SBucket) actionToCannedAction(actions []string) string {
- if len(actions) == len(readActions) {
- for _, action := range actions {
- if !utils.IsInStringArray(action, readActions) {
- return ""
- }
- }
- return "Read"
- } else if len(actions) == len(fullControlActions) {
- for _, action := range actions {
- if !utils.IsInStringArray(action, fullControlActions) {
- return ""
- }
- }
- return "FullControl"
- } else if len(actions) == len(readWriteActions) {
- for _, action := range actions {
- if !utils.IsInStringArray(action, readWriteActions) {
- return ""
- }
- }
- return "ReadWrite"
- } else {
- return ""
- }
- }
- func (b *SBucket) getResourcePaths(paths []string) []string {
- res := []string{}
- for _, path := range paths {
- res = append(res, strings.TrimPrefix(path, b.Name))
- }
- return res
- }
- func getLocalPrincipalId(principals []string) []string {
- res := []string{}
- for _, principal := range principals {
- res = append(res, ":"+principal)
- }
- return res
- }
|