diff --git a/pkg/cloudprovider/cdn.go b/pkg/cloudprovider/cdn.go index 4e94fa7d48..e29eadeffa 100644 --- a/pkg/cloudprovider/cdn.go +++ b/pkg/cloudprovider/cdn.go @@ -44,6 +44,9 @@ type SCdnOrigin struct { ServerName string Protocol string Path string + Port int + Enabled string + Priority int } // +onecloud:model-api-gen diff --git a/pkg/compute/models/cdn_domains.go b/pkg/compute/models/cdn_domains.go index 1c8054b72f..aad00c71dc 100644 --- a/pkg/compute/models/cdn_domains.go +++ b/pkg/compute/models/cdn_domains.go @@ -183,6 +183,14 @@ func (self *SCDNDomain) syncRemoveCloudCDNDomain(ctx context.Context, userCred m return nil } +// 判断资源是否可以删除 +func (self *SCDNDomain) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error { + if self.DisableDelete.IsTrue() { + return httperrors.NewInvalidStatusError("CDN is locked, cannot delete") + } + return self.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx, nil) +} + func (self *SCDNDomain) GetICloudCDNDomain() (cloudprovider.ICloudCDNDomain, error) { manager := self.GetCloudprovider() if manager == nil { diff --git a/pkg/multicloud/aliyun/aliyun.go b/pkg/multicloud/aliyun/aliyun.go index 4d3ee09aea..e2454adfa9 100644 --- a/pkg/multicloud/aliyun/aliyun.go +++ b/pkg/multicloud/aliyun/aliyun.go @@ -77,6 +77,7 @@ const ( ALIYUN_SERVICE_SLB = "slb" ALIYUN_SERVICE_KVS = "kvs" ALIYUN_SERVICE_NAS = "nas" + ALIYUN_SERVICE_CDN = "cdn" ALIYUN_SERVICE_MONGO_DB = "mongodb" ) @@ -693,6 +694,7 @@ func (region *SAliyunClient) GetCapabilities() []string { cloudprovider.CLOUD_CAPABILITY_MONGO_DB + cloudprovider.READ_ONLY_SUFFIX, cloudprovider.CLOUD_CAPABILITY_ES + cloudprovider.READ_ONLY_SUFFIX, cloudprovider.CLOUD_CAPABILITY_KAFKA + cloudprovider.READ_ONLY_SUFFIX, + cloudprovider.CLOUD_CAPABILITY_CDN + cloudprovider.READ_ONLY_SUFFIX, } return caps } diff --git a/pkg/multicloud/aliyun/bucket.go b/pkg/multicloud/aliyun/bucket.go index 8d98eec9e4..28900dd86f 100644 --- a/pkg/multicloud/aliyun/bucket.go +++ b/pkg/multicloud/aliyun/bucket.go @@ -702,17 +702,10 @@ func (b *SBucket) GetCdnDomains() ([]cloudprovider.SCdnDomain, error) { 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]) + domain, _ := b.region.client.GetCDNDomainByName(cdnDomains.DomainsData[i].Domains.DomainNames[j]) + if domain != nil { + area = domain.Coverage } - 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), diff --git a/pkg/multicloud/aliyun/cdn.go b/pkg/multicloud/aliyun/cdn.go index 7f45c26cc9..4bd192c2ce 100644 --- a/pkg/multicloud/aliyun/cdn.go +++ b/pkg/multicloud/aliyun/cdn.go @@ -15,14 +15,21 @@ package aliyun import ( + "fmt" + "strings" "time" - "github.com/pkg/errors" + "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" ) type SCdnDomainNames struct { DomainNames []string `json:"domainNames"` } + type SDomainInfo struct { DomainCname string `json:"DomainCname"` Status string `json:"Status"` @@ -30,14 +37,17 @@ type SDomainInfo struct { 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"` } @@ -49,10 +59,16 @@ type SCdnSource struct { Content string `json:"Content"` Priority string `json:"Priority"` } + type SCdnSources struct { Source []SCdnSource `json:"Source"` } -type SCdnPageData struct { + +type SCdnDomain struct { + multicloud.SResourceBase + + client *SAliyunClient + Cname string `json:"Cname"` Description string `json:"Description"` CdnType string `json:"CdnType"` @@ -65,9 +81,162 @@ type SCdnPageData struct { GmtModified string `json:"GmtModified"` Sandbox string `json:"Sandbox"` GmtCreated time.Time `json:"GmtCreated"` + SourceModels struct { + SourceModel []struct { + Content string + Type string + Port int + Enabled string + Priority int + Weight string + } + } } -type SCdnDomains struct { - PageData []SCdnPageData `json:"PageData"` + +func (self *SCdnDomain) GetArea() string { + switch self.Coverage { + case "domestic": + return api.CDN_DOMAIN_AREA_MAINLAND + case "global": + return api.CDN_DOMAIN_AREA_GLOBAL + case "overseas": + return api.CDN_DOMAIN_AREA_OVERSEAS + default: + return self.Coverage + } +} + +func (self *SCdnDomain) GetCname() string { + return self.Cname +} + +func (self *SCdnDomain) GetEnabled() bool { + return self.DomainStatus != "offline" +} + +func (self *SCdnDomain) GetId() string { + return self.DomainName +} + +func (self *SCdnDomain) GetGlobalId() string { + return self.DomainName +} + +func (self *SCdnDomain) GetName() string { + return self.DomainName +} + +func (self *SCdnDomain) Refresh() error { + domain, err := self.client.GetCdnDomain(self.DomainName) + if err != nil { + return errors.Wrapf(err, "GetCdnDomain") + } + self.DomainStatus = domain.DomainStatus + return nil +} + +func (self *SCdnDomain) GetTags() (map[string]string, error) { + _, tags, err := self.client.GetRegion("").ListSysAndUserTags(ALIYUN_SERVICE_CDN, "DOMAIN", self.DomainName) + if err != nil { + return nil, errors.Wrapf(err, "ListTags") + } + tagMaps := map[string]string{} + for k, v := range tags { + tagMaps[strings.ToLower(k)] = v + } + return tagMaps, nil +} + +func (self *SCdnDomain) GetSysTags() map[string]string { + tags, _, err := self.client.GetRegion("").ListSysAndUserTags(ALIYUN_SERVICE_CDN, "DOMAIN", self.DomainName) + if err != nil { + return nil + } + tagMaps := map[string]string{} + for k, v := range tags { + tagMaps[strings.ToLower(k)] = v + } + return tagMaps +} + +func (self *SCdnDomain) SetTags(tags map[string]string, replace bool) error { + return self.client.GetRegion("").SetResourceTags(ALIYUN_SERVICE_CDN, "DOMAIN", self.DomainName, tags, replace) +} + +func (self *SCdnDomain) GetOrigins() *cloudprovider.SCdnOrigins { + domain, err := self.client.GetCdnDomain(self.DomainName) + if err != nil { + return nil + } + ret := cloudprovider.SCdnOrigins{} + for _, origin := range domain.SourceModels.SourceModel { + ret = append(ret, cloudprovider.SCdnOrigin{ + Type: origin.Type, + Origin: origin.Content, + Port: origin.Port, + Enabled: origin.Enabled, + Priority: origin.Priority, + }) + } + return &ret +} + +func (self *SCdnDomain) GetServiceType() string { + return self.CdnType +} + +func (self *SCdnDomain) GetStatus() string { + switch self.DomainStatus { + case "online", "offline": + return self.DomainStatus + case "configuring", "checking": + return api.CDN_DOMAIN_STATUS_PROCESSING + case "configure_failed": + return self.DomainStatus + case "check_failed": + return api.CDN_DOMAIN_STATUS_REJECTED + } + return self.DomainStatus +} + +func (self *SCdnDomain) Delete() error { + params := map[string]string{ + "DomainName": self.DomainName, + } + _, err := self.client.cdnRequest("DeleteCdnDomain", params) + return errors.Wrapf(err, "DeleteCdnDomain") +} + +func (self *SAliyunClient) GetICloudCDNDomains() ([]cloudprovider.ICloudCDNDomain, error) { + domains, err := self.GetCdnDomains() + if err != nil { + return nil, errors.Wrapf(err, "GetCdnDomains") + } + ret := []cloudprovider.ICloudCDNDomain{} + for i := range domains { + domains[i].client = self + ret = append(ret, &domains[i]) + } + return ret, nil +} + +func (self *SAliyunClient) GetICloudCDNDomainByName(name string) (cloudprovider.ICloudCDNDomain, error) { + return self.GetCDNDomainByName(name) +} + +func (self *SAliyunClient) GetCDNDomainByName(name string) (*SCdnDomain, error) { + domains, total, err := self.DescribeUserDomains(name, 1, 1) + if err != nil { + return nil, errors.Wrapf(err, "GetCdnDomain") + } + if total == 1 { + domains[0].client = self + return &domains[0], nil + } + if total == 0 { + return nil, errors.Wrapf(cloudprovider.ErrNotFound, name) + } + return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, name) } func (client *SAliyunClient) DescribeDomainsBySource(origin string) (SCdnDomainsList, error) { @@ -86,19 +255,61 @@ func (client *SAliyunClient) DescribeDomainsBySource(origin string) (SCdnDomains 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" +func (self *SAliyunClient) GetCdnDomains() ([]SCdnDomain, error) { + domains := []SCdnDomain{} + for { + part, total, err := self.DescribeUserDomains("", 50, len(domains)/50+1) + if err != nil { + return nil, errors.Wrapf(err, "DescribeUserDomains") + } + domains = append(domains, part...) + if len(domains) >= total || len(part) == 0 { + break + } + } + return domains, nil +} + +func (client *SAliyunClient) DescribeUserDomains(domain string, pageSize, pageNumber int) ([]SCdnDomain, int, error) { + if pageSize < 1 || pageSize > 50 { + pageSize = 50 + } + if pageNumber < 1 { + pageNumber = 1 + } + params := map[string]string{ + "PageSize": fmt.Sprintf("%d", pageSize), + "PageNumber": fmt.Sprintf("%d", pageNumber), + } + if len(domain) > 0 { + params["DomainName"] = domain + params["DomainSearchType"] = "full_match" + } resp, err := client.cdnRequest("DescribeUserDomains", params) if err != nil { - return sproducts, errors.Wrap(err, "DescribeUserDomains") + return nil, 0, errors.Wrap(err, "DescribeUserDomains") } - err = resp.Unmarshal(&sproducts, "Domains") + domains := []SCdnDomain{} + err = resp.Unmarshal(&domains, "Domains", "PageData") if err != nil { - return sproducts, errors.Wrap(err, "resp.Unmarshal") + return nil, 0, errors.Wrap(err, "resp.Unmarshal") } - return sproducts, nil + totalCount, _ := resp.Int("TotalCount") + return domains, int(totalCount), nil +} + +func (self *SAliyunClient) GetCdnDomain(domainName string) (*SCdnDomain, error) { + params := map[string]string{ + "DomainName": domainName, + } + resp, err := self.cdnRequest("DescribeCdnDomainDetail", params) + if err != nil { + return nil, errors.Wrapf(err, "DescribeCdnDomainDetail") + } + domain := &SCdnDomain{client: self} + err = resp.Unmarshal(domain, "GetDomainDetailModel") + if err != nil { + return nil, errors.Wrapf(err, "resp.Unmarshal") + } + return domain, nil } diff --git a/pkg/multicloud/aliyun/provider/provider.go b/pkg/multicloud/aliyun/provider/provider.go index ad6666d4ff..c7efbb941f 100644 --- a/pkg/multicloud/aliyun/provider/provider.go +++ b/pkg/multicloud/aliyun/provider/provider.go @@ -499,3 +499,11 @@ func (self *SAliyunProvider) CreateICloudSAMLProvider(opts *cloudprovider.SAMLPr } return sp, nil } + +func (self *SAliyunProvider) GetICloudCDNDomains() ([]cloudprovider.ICloudCDNDomain, error) { + return self.client.GetICloudCDNDomains() +} + +func (self *SAliyunProvider) GetICloudCDNDomainByName(name string) (cloudprovider.ICloudCDNDomain, error) { + return self.client.GetICloudCDNDomainByName(name) +} diff --git a/pkg/multicloud/aliyun/resource_tags.go b/pkg/multicloud/aliyun/resource_tags.go index 07d0ba9b59..3ce3de4c26 100644 --- a/pkg/multicloud/aliyun/resource_tags.go +++ b/pkg/multicloud/aliyun/resource_tags.go @@ -40,6 +40,8 @@ func (self *SRegion) tagRequest(serviceType, action string, params map[string]st return self.nasRequest(action, params) case ALIYUN_SERVICE_MONGO_DB: return self.mongodbRequest(action, params) + case ALIYUN_SERVICE_CDN: + return self.client.cdnRequest(action, params) default: return nil, fmt.Errorf("invalid service type") } diff --git a/pkg/multicloud/aliyun/shell/cdn.go b/pkg/multicloud/aliyun/shell/cdn.go index 1dc0c86435..5d0be67554 100644 --- a/pkg/multicloud/aliyun/shell/cdn.go +++ b/pkg/multicloud/aliyun/shell/cdn.go @@ -34,27 +34,30 @@ import ( ) func init() { - type CdnDomainList struct { - Origin string + type CdnDomainListOptions struct { + Domain string + PageSize int + PageNumber int } - 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 + shellutils.R(&CdnDomainListOptions{}, "cdn-domain-list", "list cdn domain", func(cli *aliyun.SRegion, args *CdnDomainListOptions) error { + domains, _, err := cli.GetClient().DescribeUserDomains(args.Domain, args.PageSize, args.PageNumber) + if err != nil { + return err } - printList(domainlist.DomainsData, len(domainlist.DomainsData), 1, len(domainlist.DomainsData), []string{}) + printList(domains, 0, 0, 0, []string{}) return nil }) - type CdnDomainShow struct { + type CdnDomainShowOptions 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 + shellutils.R(&CdnDomainShowOptions{}, "cdn-domain-show", "Show cdn domain", func(cli *aliyun.SRegion, args *CdnDomainShowOptions) error { + domain, err := cli.GetClient().GetCdnDomain(args.DOMAIN) + if err != nil { + return err } - printList(domainlist.PageData, len(domainlist.PageData), 1, len(domainlist.PageData), []string{}) + printObject(domain) return nil }) + }