feat(region): 多云 bucket website.cors,referer 配置

This commit is contained in:
lvyangyang
2020-12-03 11:31:51 +08:00
parent d0a2f43484
commit 8a9ec04f9f
12 changed files with 764 additions and 97 deletions
+85 -1
View File
@@ -250,7 +250,7 @@ type ICloudBucket interface {
SetCORS(rules []SBucketCORSRule) error
GetCORSRules() ([]SBucketCORSRule, error)
DeleteCORS(id []string) ([]SBucketCORSRule, error)
DeleteCORS() error
SetReferer(conf SBucketRefererConf) error
GetReferer() (SBucketRefererConf, error)
@@ -738,3 +738,87 @@ func FetchMetaFromHttpHeader(metaPrefix string, headers http.Header) http.Header
}
return meta
}
func SetBucketCORS(ibucket ICloudBucket, rules []SBucketCORSRule) error {
if len(rules) == 0 {
return nil
}
oldRules, err := ibucket.GetCORSRules()
if err != nil {
return errors.Wrap(err, "ibucket.GetCORSRules()")
}
newSet := []SBucketCORSRule{}
updateSet := map[int]SBucketCORSRule{}
for i := range rules {
index, err := strconv.Atoi(rules[i].Id)
if err == nil && index < len(oldRules) {
updateSet[index] = rules[i]
} else {
newSet = append(newSet, rules[i])
}
}
updatedRules := []SBucketCORSRule{}
for i := range oldRules {
if _, ok := updateSet[i]; !ok {
updatedRules = append(updatedRules, oldRules[i])
} else {
updatedRules = append(updatedRules, updateSet[i])
}
}
updatedRules = append(updatedRules, newSet...)
err = ibucket.SetCORS(updatedRules)
if err != nil {
return errors.Wrap(err, "ibucket.SetCORS(updatedRules)")
}
return nil
}
func DeleteBucketCORS(ibucket ICloudBucket, id []string) ([]SBucketCORSRule, error) {
if len(id) == 0 {
return nil, nil
}
deletedRules := []SBucketCORSRule{}
oldRules, err := ibucket.GetCORSRules()
if err != nil {
return nil, errors.Wrap(err, "ibucket.GetCORSRules()")
}
excludeMap := map[int]bool{}
for i := range id {
index, err := strconv.Atoi(id[i])
if err == nil && index < len(oldRules) {
excludeMap[index] = true
}
}
if len(excludeMap) == 0 {
return nil, nil
}
newRules := []SBucketCORSRule{}
for i := range oldRules {
if _, ok := excludeMap[i]; !ok {
newRules = append(newRules, oldRules[i])
} else {
deletedRules = append(deletedRules, oldRules[i])
}
}
if len(newRules) == 0 {
err = ibucket.DeleteCORS()
if err != nil {
return nil, errors.Wrapf(err, "ibucket.DeleteCORS()")
}
} else {
err = ibucket.SetCORS(newRules)
if err != nil {
return nil, errors.Wrapf(err, "ibucket.SetBucketCORS(newRules)")
}
}
return deletedRules, nil
}
+3 -3
View File
@@ -1377,9 +1377,9 @@ func (bucket *SBucket) PerformSetCors(
Id: input.Data[i].Id,
})
}
err = iBucket.SetCORS(rules)
err = cloudprovider.SetBucketCORS(iBucket, rules)
if err != nil {
return nil, httperrors.NewInternalServerError("iBucket.SetCORS error %s", err)
return nil, httperrors.NewInternalServerError("cloudprovider.SetBucketCORS error %s", err)
}
db.OpsLog.LogEvent(bucket, db.ACT_SET_CORS, rules, userCred)
logclient.AddActionLogWithContext(ctx, bucket, logclient.ACT_SET_CORS, rules, userCred, true)
@@ -1404,7 +1404,7 @@ func (bucket *SBucket) PerformDeleteCors(
if err != nil {
return nil, errors.Wrap(err, "GetIBucket")
}
result, err := iBucket.DeleteCORS(input.Id)
result, err := cloudprovider.DeleteBucketCORS(iBucket, input.Id)
if err != nil {
return nil, httperrors.NewInternalServerError("iBucket.DeleteCORS error %s", err)
}
+9
View File
@@ -60,6 +60,7 @@ const (
ALIYUN_PVTZ_API_VERSION = "2018-01-01"
ALIYUN_ALIDNS_API_VERSION = "2015-01-09"
ALIYUN_CBN_API_VERSION = "2017-09-12"
ALIYUN_CDN_API_VERSION = "2018-05-10"
)
var (
@@ -290,6 +291,14 @@ func (self *SAliyunClient) cbnRequest(apiName string, params map[string]string)
return jsonRequest(cli, "cbn.aliyuncs.com", ALIYUN_CBN_API_VERSION, apiName, params, self.debug)
}
func (self *SAliyunClient) cdnRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := self.getDefaultClient()
if err != nil {
return nil, err
}
return jsonRequest(cli, "cdn.aliyuncs.com", ALIYUN_CDN_API_VERSION, apiName, params, self.debug)
}
func (self *SAliyunClient) fetchRegions() error {
body, err := self.ecsRequest("DescribeRegions", map[string]string{"AcceptLanguage": "zh-CN"})
if err != nil {
+213
View File
@@ -19,13 +19,17 @@ import (
"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"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
@@ -502,3 +506,212 @@ func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, par
}
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")
}
err = osscli.SetBucketReferer(b.Name, conf.WhiteList, conf.AllowEmptyRefer)
if err != nil {
return errors.Wrapf(err, "osscli.SetBucketReferer(%s,%s,%d)", b.Name, conf.WhiteList, 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{
WhiteList: 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 := ""
cdnDomianDescribes, err := b.region.client.DescribeUserDomains(cdnDomains.DomainsData[i].Domains.DomainNames[j])
if err != nil {
return nil, errors.Wrapf(err, "b.region.client.DescribeUserDomains(%s)", cdnDomains.DomainsData[i].Domains.DomainNames[j])
}
for k := range cdnDomianDescribes.PageData {
if cdnDomianDescribes.PageData[k].DomainName == cdnDomains.DomainsData[i].Domains.DomainNames[j] {
area = cdnDomianDescribes.PageData[k].Coverage
break
}
}
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
}
+104
View File
@@ -0,0 +1,104 @@
// 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 (
"time"
"github.com/pkg/errors"
)
type SCdnDomainNames struct {
DomainNames []string `json:"domainNames"`
}
type SDomainInfo struct {
DomainCname string `json:"DomainCname"`
Status string `json:"Status"`
CreateTime time.Time `json:"CreateTime"`
UpdateTime time.Time `json:"UpdateTime"`
DomainName string `json:"DomainName"`
}
type SCdnDomainInfos struct {
DomainInfo []SDomainInfo `json:"domainInfo"`
}
type SCdnDomainsData struct {
Source string `json:"Source"`
Domains SCdnDomainNames `json:"Domains"`
DomainInfos SCdnDomainInfos `json:"DomainInfos"`
}
type SCdnDomainsList struct {
DomainsData []SCdnDomainsData `json:"DomainsData"`
}
type SCdnSource struct {
Port int `json:"Port"`
Weight string `json:"Weight"`
Type string `json:"Type"`
Content string `json:"Content"`
Priority string `json:"Priority"`
}
type SCdnSources struct {
Source []SCdnSource `json:"Source"`
}
type SCdnPageData struct {
Cname string `json:"Cname"`
Description string `json:"Description"`
CdnType string `json:"CdnType"`
ResourceGroupID string `json:"ResourceGroupId"`
DomainStatus string `json:"DomainStatus"`
SslProtocol string `json:"SslProtocol"`
DomainName string `json:"DomainName"`
Coverage string `json:"Coverage"`
Sources SCdnSource `json:"Sources"`
GmtModified string `json:"GmtModified"`
Sandbox string `json:"Sandbox"`
GmtCreated time.Time `json:"GmtCreated"`
}
type SCdnDomains struct {
PageData []SCdnPageData `json:"PageData"`
}
func (client *SAliyunClient) DescribeDomainsBySource(origin string) (SCdnDomainsList, error) {
sproducts := SCdnDomainsList{}
params := map[string]string{}
params["Action"] = "DescribeDomainsBySource"
params["Sources"] = origin
resp, err := client.cdnRequest("DescribeDomainsBySource", params)
if err != nil {
return sproducts, errors.Wrap(err, "DescribeDomainsBySource")
}
err = resp.Unmarshal(&sproducts, "DomainsList")
if err != nil {
return sproducts, errors.Wrap(err, "resp.Unmarshal")
}
return sproducts, nil
}
func (client *SAliyunClient) DescribeUserDomains(domain string) (SCdnDomains, error) {
sproducts := SCdnDomains{}
params := map[string]string{}
params["Action"] = "DescribeUserDomains"
params["DomainName"] = domain
params["DomainSearchType"] = "full_match"
resp, err := client.cdnRequest("DescribeUserDomains", params)
if err != nil {
return sproducts, errors.Wrap(err, "DescribeUserDomains")
}
err = resp.Unmarshal(&sproducts, "Domains")
if err != nil {
return sproducts, errors.Wrap(err, "resp.Unmarshal")
}
return sproducts, nil
}
+46
View File
@@ -0,0 +1,46 @@
// 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
// PageSizeations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type CdnDomainList struct {
Origin string
}
shellutils.R(&CdnDomainList{}, "cdn-domain-list", "List cdn domain", func(cli *aliyun.SRegion, args *CdnDomainList) error {
domainlist, e := cli.GetClient().DescribeDomainsBySource(args.Origin)
if e != nil {
return e
}
printList(domainlist.DomainsData, len(domainlist.DomainsData), 1, len(domainlist.DomainsData), []string{})
return nil
})
type CdnDomainShow struct {
DOMAIN string
}
shellutils.R(&CdnDomainShow{}, "cdn-domain-show", "show cdn domain", func(cli *aliyun.SRegion, args *CdnDomainShow) error {
domainlist, e := cli.GetClient().DescribeUserDomains(args.DOMAIN)
if e != nil {
return e
}
printList(domainlist.PageData, len(domainlist.PageData), 1, len(domainlist.PageData), []string{})
return nil
})
}
+164
View File
@@ -20,11 +20,14 @@ import (
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/s3"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/s3cli"
@@ -145,6 +148,10 @@ func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
}
}
func (b *SBucket) GetWebsiteUrl() string {
return fmt.Sprintf("http://%s.%s", b.Name, b.region.getS3WebsiteEndpoint())
}
func (b *SBucket) GetStats() cloudprovider.SBucketStats {
stats, _ := cloudprovider.GetIBucketStats(b)
return stats
@@ -514,3 +521,160 @@ func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, par
}
return *output.CopyPartResult.ETag, nil
}
func (b *SBucket) SetWebsite(websitConf cloudprovider.SBucketWebsiteConf) error {
s3cli, err := b.region.GetS3Client()
if err != nil {
return errors.Wrap(err, "GetS3Client")
}
s3WebConf := s3.WebsiteConfiguration{}
s3WebConf.SetIndexDocument(&s3.IndexDocument{Suffix: &websitConf.Index})
s3WebConf.SetErrorDocument(&s3.ErrorDocument{Key: &websitConf.ErrorDocument})
input := s3.PutBucketWebsiteInput{}
input.SetBucket(b.Name)
input.SetWebsiteConfiguration(&s3WebConf)
_, err = s3cli.PutBucketWebsite(&input)
if err != nil {
return errors.Wrapf(err, "s3cli.PutBucketWebsite(%s)", jsonutils.Marshal(input).String())
}
return nil
}
func (b *SBucket) GetWebsiteConf() (cloudprovider.SBucketWebsiteConf, error) {
result := cloudprovider.SBucketWebsiteConf{}
s3cli, err := b.region.GetS3Client()
if err != nil {
return result, errors.Wrap(err, "GetS3Client")
}
input := s3.GetBucketWebsiteInput{}
input.SetBucket(b.Name)
webconfResult, err := s3cli.GetBucketWebsite(&input)
if err != nil {
return result, errors.Wrapf(err, "s3cli.GetBucketWebsite(%s)", b.Name)
}
if webconfResult.IndexDocument != nil && webconfResult.IndexDocument.Suffix != nil {
result.Index = *webconfResult.IndexDocument.Suffix
}
if webconfResult.ErrorDocument != nil && webconfResult.ErrorDocument.Key != nil {
result.ErrorDocument = *webconfResult.ErrorDocument.Key
}
result.Url = b.GetWebsiteUrl()
return result, nil
}
func (b *SBucket) DeleteWebSiteConf() error {
s3cli, err := b.region.GetS3Client()
if err != nil {
return errors.Wrap(err, "GetS3Client")
}
input := s3.DeleteBucketWebsiteInput{}
input.SetBucket(b.Name)
_, err = s3cli.DeleteBucketWebsite(&input)
if err != nil {
return errors.Wrapf(err, "s3cli.DeleteBucketWebsite(%s)", b.Name)
}
return nil
}
func InputToAwsApiSliceString(input []string) []*string {
result := []*string{}
for i := range input {
result = append(result, &input[i])
}
return result
}
func InputToAwsApiInt64(input int64) *int64 {
return &input
}
func AwsApiSliceStringToOutput(input []*string) []string {
result := []string{}
for i := range input {
if input[i] != nil {
result = append(result, *input[i])
} else {
result = append(result, "")
}
}
return result
}
func AwsApiInt64ToOutput(input *int64) int64 {
if input == nil {
return 0
}
return *input
}
func (b *SBucket) SetCORS(rules []cloudprovider.SBucketCORSRule) error {
s3cli, err := b.region.GetS3Client()
if err != nil {
return errors.Wrap(err, "GetS3Client")
}
opts := []*s3.CORSRule{}
for i := range rules {
opts = append(opts, &s3.CORSRule{
AllowedOrigins: InputToAwsApiSliceString(rules[i].AllowedOrigins),
AllowedMethods: InputToAwsApiSliceString(rules[i].AllowedMethods),
AllowedHeaders: InputToAwsApiSliceString(rules[i].AllowedHeaders),
MaxAgeSeconds: InputToAwsApiInt64(int64(rules[i].MaxAgeSeconds)),
ExposeHeaders: InputToAwsApiSliceString(rules[i].ExposeHeaders),
})
}
input := s3.PutBucketCorsInput{}
input.SetBucket(b.Name)
input.SetCORSConfiguration(&s3.CORSConfiguration{CORSRules: opts})
_, err = s3cli.PutBucketCors(&input)
if err != nil {
return errors.Wrapf(err, "s3cli.PutBucketCors(%s)", input)
}
return nil
}
func (b *SBucket) GetCORSRules() ([]cloudprovider.SBucketCORSRule, error) {
s3cli, err := b.region.GetS3Client()
if err != nil {
return nil, errors.Wrap(err, "GetS3Client")
}
input := s3.GetBucketCorsInput{}
input.SetBucket(b.Name)
conf, err := s3cli.GetBucketCors(&input)
if err != nil {
if !strings.Contains(err.Error(), "NoSuchCORSConfiguration") {
return nil, errors.Wrapf(err, "s3cli.GetBucketCors(%s)", b.Name)
}
}
if conf == nil {
return nil, nil
}
result := []cloudprovider.SBucketCORSRule{}
for i := range conf.CORSRules {
result = append(result, cloudprovider.SBucketCORSRule{
AllowedOrigins: AwsApiSliceStringToOutput(conf.CORSRules[i].AllowedOrigins),
AllowedMethods: AwsApiSliceStringToOutput(conf.CORSRules[i].AllowedMethods),
AllowedHeaders: AwsApiSliceStringToOutput(conf.CORSRules[i].AllowedHeaders),
MaxAgeSeconds: int(AwsApiInt64ToOutput(conf.CORSRules[i].MaxAgeSeconds)),
ExposeHeaders: AwsApiSliceStringToOutput(conf.CORSRules[i].ExposeHeaders),
Id: strconv.Itoa(i),
})
}
return result, nil
}
func (b *SBucket) DeleteCORS() error {
s3cli, err := b.region.GetS3Client()
if err != nil {
return errors.Wrap(err, "GetS3Client")
}
input := s3.DeleteBucketCorsInput{}
input.SetBucket(b.Name)
_, err = s3cli.DeleteBucketCors(&input)
if err != nil {
return errors.Wrapf(err, "s3cli.DeleteBucketCors(%s)", b.Name)
}
return nil
}
+8
View File
@@ -1026,6 +1026,14 @@ func (region *SRegion) getS3Endpoint() string {
return ""
}
func (region *SRegion) getS3WebsiteEndpoint() string {
base := region.getBaseEndpoint()
if len(base) > 0 {
return "s3-website." + base
}
return ""
}
func (region *SRegion) getEc2Endpoint() string {
return region.RegionEndpoint
}
+2 -2
View File
@@ -94,8 +94,8 @@ func (b *SBaseBucket) GetCORSRules() ([]cloudprovider.SBucketCORSRule, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (b *SBaseBucket) DeleteCORS(id []string) ([]cloudprovider.SBucketCORSRule, error) {
return nil, cloudprovider.ErrNotImplemented
func (b *SBaseBucket) DeleteCORS() error {
return cloudprovider.ErrNotImplemented
}
func (b *SBaseBucket) SetReferer(conf cloudprovider.SBucketRefererConf) error {
+116
View File
@@ -19,6 +19,8 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
"yunion.io/x/log"
@@ -557,3 +559,117 @@ func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, par
}
return output.ETag, nil
}
func (b *SBucket) SetWebsite(websitConf cloudprovider.SBucketWebsiteConf) error {
obscli, err := b.region.getOBSClient()
if err != nil {
return errors.Wrap(err, "GetOBSClient")
}
obsWebConf := obs.SetBucketWebsiteConfigurationInput{}
obsWebConf.Bucket = b.Name
obsWebConf.BucketWebsiteConfiguration = obs.BucketWebsiteConfiguration{
IndexDocument: obs.IndexDocument{Suffix: websitConf.Index},
ErrorDocument: obs.ErrorDocument{Key: websitConf.ErrorDocument},
}
_, err = obscli.SetBucketWebsiteConfiguration(&obsWebConf)
if err != nil {
return errors.Wrap(err, "obscli.SetBucketWebsiteConfiguration(&obsWebConf)")
}
return nil
}
func (b *SBucket) GetWebsiteConf() (cloudprovider.SBucketWebsiteConf, error) {
result := cloudprovider.SBucketWebsiteConf{}
obscli, err := b.region.getOBSClient()
if err != nil {
return result, errors.Wrap(err, "GetOBSClient")
}
out, err := obscli.GetBucketWebsiteConfiguration(b.Name)
if out == nil {
return result, nil
}
result.Index = out.IndexDocument.Suffix
result.ErrorDocument = out.ErrorDocument.Key
result.Url = fmt.Sprintf("https://%s.obs-website.%s.myhuaweicloud.com", b.Name, b.region.GetId())
return result, nil
}
func (b *SBucket) DeleteWebSiteConf() error {
obscli, err := b.region.getOBSClient()
if err != nil {
return errors.Wrap(err, "GetOBSClient")
}
_, err = obscli.DeleteBucketWebsiteConfiguration(b.Name)
if err != nil {
return errors.Wrapf(err, "obscli.DeleteBucketWebsiteConfiguration(%s)", b.Name)
}
return nil
}
func (b *SBucket) SetCORS(rules []cloudprovider.SBucketCORSRule) error {
obscli, err := b.region.getOBSClient()
if err != nil {
return errors.Wrap(err, "GetOBSClient")
}
opts := []obs.CorsRule{}
for i := range rules {
opts = append(opts, obs.CorsRule{
AllowedOrigin: rules[i].AllowedOrigins,
AllowedMethod: rules[i].AllowedMethods,
AllowedHeader: rules[i].AllowedHeaders,
MaxAgeSeconds: rules[i].MaxAgeSeconds,
ExposeHeader: rules[i].ExposeHeaders,
})
}
input := obs.SetBucketCorsInput{}
input.Bucket = b.Name
input.BucketCors.CorsRules = opts
_, err = obscli.SetBucketCors(&input)
if err != nil {
return errors.Wrapf(err, "obscli.SetBucketCors(%s)", input)
}
return nil
}
func (b *SBucket) GetCORSRules() ([]cloudprovider.SBucketCORSRule, error) {
obscli, err := b.region.getOBSClient()
if err != nil {
return nil, errors.Wrap(err, "GetOBSClient")
}
conf, err := obscli.GetBucketCors(b.Name)
if err != nil {
if !strings.Contains(err.Error(), "NoSuchCORSConfiguration") {
return nil, errors.Wrapf(err, "obscli.GetBucketCors(%s)", b.Name)
}
}
if conf == nil {
return nil, nil
}
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 {
obscli, err := b.region.getOBSClient()
if err != nil {
return errors.Wrap(err, "GetOBSClient")
}
_, err = obscli.DeleteBucketCors(b.Name)
if err != nil {
return errors.Wrapf(err, "obscli.DeleteBucketCors(%s)", b.Name)
}
return nil
}
+2 -2
View File
@@ -466,7 +466,7 @@ func S3Shell() {
ExposeHeaders: args.ExposeHeaders,
Id: args.Id,
}
err = bucket.SetCORS([]cloudprovider.SBucketCORSRule{rule})
err = cloudprovider.SetBucketCORS(bucket, []cloudprovider.SBucketCORSRule{rule})
if err != nil {
return err
}
@@ -499,7 +499,7 @@ func S3Shell() {
if err != nil {
return err
}
result, err := bucket.DeleteCORS(args.Ids)
result, err := cloudprovider.DeleteBucketCORS(bucket, args.Ids)
if err != nil {
return err
}
+12 -89
View File
@@ -625,21 +625,16 @@ func (b *SBucket) DeleteWebSiteConf() error {
}
func (b *SBucket) SetCORS(rules []cloudprovider.SBucketCORSRule) error {
for i := range rules {
if len(rules[i].AllowedOrigins) == 0 {
return errors.Wrap(cloudprovider.ErrNotSupported, "missing AllowedOrigins")
}
if len(rules[i].AllowedMethods) == 0 {
return errors.Wrap(cloudprovider.ErrNotSupported, "missing AllowedMethods")
}
if len(rules) == 0 {
return nil
}
coscli, err := b.region.GetCosClient(b)
if err != nil {
return errors.Wrap(err, "b.region.GetCosClient")
}
opts := cos.BucketPutCORSOptions{}
input := cos.BucketPutCORSOptions{}
for i := range rules {
opts.Rules = append(opts.Rules, cos.BucketCORSRule{
input.Rules = append(input.Rules, cos.BucketCORSRule{
AllowedOrigins: rules[i].AllowedOrigins,
AllowedMethods: rules[i].AllowedMethods,
AllowedHeaders: rules[i].AllowedHeaders,
@@ -649,36 +644,7 @@ func (b *SBucket) SetCORS(rules []cloudprovider.SBucketCORSRule) error {
})
}
newSet := []cos.BucketCORSRule{}
updateSet := map[int]cos.BucketCORSRule{}
oldConf, _, err := coscli.Bucket.GetCORS(context.Background())
if err != nil {
if !strings.Contains(err.Error(), "NoSuchCORSConfiguration") {
return errors.Wrap(err, "b.region.GetCORS")
}
}
for i := range opts.Rules {
index, err := strconv.Atoi(opts.Rules[i].ID)
if err == nil && index < len(oldConf.Rules) {
updateSet[index] = opts.Rules[i]
} else {
newSet = append(newSet, opts.Rules[i])
}
}
updatedOpts := cos.BucketPutCORSOptions{}
for i := range oldConf.Rules {
if _, ok := updateSet[i]; !ok {
updatedOpts.Rules = append(updatedOpts.Rules, oldConf.Rules[i])
} else {
updatedOpts.Rules = append(updatedOpts.Rules, updateSet[i])
}
}
updatedOpts.Rules = append(updatedOpts.Rules, newSet...)
_, err = coscli.Bucket.PutCORS(context.Background(), &updatedOpts)
_, err = coscli.Bucket.PutCORS(context.Background(), &input)
if err != nil {
return errors.Wrap(err, "coscli.Bucket.PutCORS")
}
@@ -711,60 +677,16 @@ func (b *SBucket) GetCORSRules() ([]cloudprovider.SBucketCORSRule, error) {
return result, nil
}
func (b *SBucket) DeleteCORS(id []string) ([]cloudprovider.SBucketCORSRule, error) {
deletedRules := []cloudprovider.SBucketCORSRule{}
func (b *SBucket) DeleteCORS() error {
coscli, err := b.region.GetCosClient(b)
if err != nil {
return nil, errors.Wrap(err, "b.region.GetCosClient")
return errors.Wrap(err, "b.region.GetCosClient")
}
existedRules := []cos.BucketCORSRule{}
if len(id) > 0 {
conf, _, err := coscli.Bucket.GetCORS(context.Background())
if err != nil {
if strings.Contains(err.Error(), "NoSuchCORSConfiguration") {
return nil, nil
}
return nil, errors.Wrap(err, "b.region.GetCORS")
}
existedRules = conf.Rules
_, err = coscli.Bucket.DeleteCORS(context.Background())
if err != nil {
return errors.Wrap(err, "coscli.Bucket.DeleteCORS")
}
excludeMap := map[int]bool{}
for i := range id {
index, err := strconv.Atoi(id[i])
if err == nil {
excludeMap[index] = true
}
}
newRules := []cos.BucketCORSRule{}
for i := range existedRules {
if _, ok := excludeMap[i]; !ok {
newRules = append(newRules, existedRules[i])
} else {
deletedRules = append(deletedRules, cloudprovider.SBucketCORSRule{
AllowedOrigins: existedRules[i].AllowedOrigins,
AllowedMethods: existedRules[i].AllowedMethods,
AllowedHeaders: existedRules[i].AllowedHeaders,
MaxAgeSeconds: existedRules[i].MaxAgeSeconds,
ExposeHeaders: existedRules[i].ExposeHeaders,
})
}
}
if len(newRules) < len(existedRules) {
if len(newRules) == 0 {
_, err = coscli.Bucket.DeleteCORS(context.Background())
if err != nil {
return nil, errors.Wrap(err, "coscli.Bucket.DeleteCORS")
}
return deletedRules, nil
}
_, err = coscli.Bucket.PutCORS(context.Background(), &cos.BucketPutCORSOptions{Rules: newRules})
if err != nil {
return nil, errors.Wrap(err, "coscli.Bucket.PutCORS")
}
}
return deletedRules, nil
return nil
}
func (b *SBucket) SetReferer(conf cloudprovider.SBucketRefererConf) error {
@@ -807,6 +729,7 @@ func (b *SBucket) GetReferer() (cloudprovider.SBucketRefererConf, error) {
result.AllowEmptyRefer = true
}
if referResult.Status == "Disabled" {
result.AllowEmptyRefer = true
return result, nil
}
result.WhiteList = referResult.DomainList