diff --git a/pkg/multicloud/aliyun/aliyun.go b/pkg/multicloud/aliyun/aliyun.go index b90199b93e..9df1bf51a9 100644 --- a/pkg/multicloud/aliyun/aliyun.go +++ b/pkg/multicloud/aliyun/aliyun.go @@ -52,6 +52,7 @@ const ( ALIYUN_RAM_API_VERSION = "2015-05-01" ALIYUN_API_VERION_RDS = "2014-08-15" + ALIYUN_RM_API_VERSION = "2020-03-31" ) type AliyunClientConfig struct { @@ -209,6 +210,14 @@ func (self *SAliyunClient) getDefaultClient() (*sdk.Client, error) { return client, err } +func (self *SAliyunClient) rmRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { + cli, err := self.getDefaultClient() + if err != nil { + return nil, err + } + return jsonRequest(cli, "resourcemanager.aliyuncs.com", ALIYUN_RM_API_VERSION, apiName, params, self.debug) +} + func (self *SAliyunClient) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { cli, err := self.getDefaultClient() if err != nil { @@ -423,11 +432,25 @@ func (self *SAliyunClient) GetIStorageById(id string) (cloudprovider.ICloudStora return nil, cloudprovider.ErrNotFound } -func (region *SAliyunClient) GetIProjects() ([]cloudprovider.ICloudProject, error) { - // 阿里云并未公布资源组的api地址 - // params := map[string]string{} - // body, err := region.ecsRequest("ListResourceGroups", params) - return nil, cloudprovider.ErrNotImplemented +func (self *SAliyunClient) GetIProjects() ([]cloudprovider.ICloudProject, error) { + pageSize, pageNumber := 50, 1 + resourceGroups := []SResourceGroup{} + for { + parts, total, err := self.GetResourceGroups(pageNumber, pageSize) + if err != nil { + return nil, errors.Wrap(err, "GetResourceGroups") + } + resourceGroups = append(resourceGroups, parts...) + if len(resourceGroups) >= total { + break + } + pageNumber += 1 + } + ret := []cloudprovider.ICloudProject{} + for i := range resourceGroups { + ret = append(ret, &resourceGroups[i]) + } + return ret, nil } func (region *SAliyunClient) GetCapabilities() []string { diff --git a/pkg/multicloud/aliyun/dbinstance.go b/pkg/multicloud/aliyun/dbinstance.go index 1eaa763670..67e51392d8 100644 --- a/pkg/multicloud/aliyun/dbinstance.go +++ b/pkg/multicloud/aliyun/dbinstance.go @@ -746,6 +746,10 @@ func (region *SRegion) RecoveryDBInstanceFromBackup(instanceId string, backupId } +func (rds *SDBInstance) GetProjectId() string { + return rds.ResourceGroupId +} + func (rds *SDBInstance) CreateDatabase(conf *cloudprovider.SDBInstanceDatabaseCreateConfig) error { return rds.region.CreateDBInstanceDatabae(rds.DBInstanceId, conf.CharacterSet, conf.Name, conf.Description) } diff --git a/pkg/multicloud/aliyun/disk.go b/pkg/multicloud/aliyun/disk.go index e633225247..e06953cf60 100644 --- a/pkg/multicloud/aliyun/disk.go +++ b/pkg/multicloud/aliyun/disk.go @@ -444,5 +444,5 @@ func (self *SRegion) rebuildDisk(diskId string) error { } func (self *SDisk) GetProjectId() string { - return "" + return self.ResourceGroupId } diff --git a/pkg/multicloud/aliyun/eip.go b/pkg/multicloud/aliyun/eip.go index b72a7e0f0c..abcb8d8a7d 100644 --- a/pkg/multicloud/aliyun/eip.go +++ b/pkg/multicloud/aliyun/eip.go @@ -87,8 +87,9 @@ type SEipAddress struct { OperationLocks string - ChargeType TChargeType - ExpiredTime time.Time + ChargeType TChargeType + ExpiredTime time.Time + ResourceGroupId string } func (self *SEipAddress) GetId() string { @@ -378,5 +379,5 @@ func (region *SRegion) UpdateEipBandwidth(eipId string, bw int) error { } func (self *SEipAddress) GetProjectId() string { - return "" + return self.ResourceGroupId } diff --git a/pkg/multicloud/aliyun/elasticcache_instance.go b/pkg/multicloud/aliyun/elasticcache_instance.go index c071b1aa25..8071bde8c6 100644 --- a/pkg/multicloud/aliyun/elasticcache_instance.go +++ b/pkg/multicloud/aliyun/elasticcache_instance.go @@ -70,6 +70,7 @@ type SElasticcache struct { NodeType string `json:"NodeType"` CapacityMB int `json:"Capacity"` Connections int64 `json:"Connections"` + ResourceGroupId string `json:"ResourceGroupId"` } type SElasticcacheAttribute struct { @@ -851,6 +852,10 @@ func (self *SElasticcache) UpdateAuthMode(noPwdAccess bool) error { return nil } +func (self *SElasticcache) GetProjectId() string { + return self.ResourceGroupId +} + func (self *SElasticcache) GetAuthMode() string { attribute, err := self.GetAttribute() if err != nil { diff --git a/pkg/multicloud/aliyun/instance.go b/pkg/multicloud/aliyun/instance.go index 996df7a8c1..a17b6e69b0 100644 --- a/pkg/multicloud/aliyun/instance.go +++ b/pkg/multicloud/aliyun/instance.go @@ -985,7 +985,7 @@ func (region *SRegion) RenewInstance(instanceId string, bc billing.SBillingCycle } func (self *SInstance) GetProjectId() string { - return "" + return self.ResourceGroupId } func (self *SInstance) GetError() error { diff --git a/pkg/multicloud/aliyun/loadbalancer.go b/pkg/multicloud/aliyun/loadbalancer.go index caf421116d..ca641ec053 100644 --- a/pkg/multicloud/aliyun/loadbalancer.go +++ b/pkg/multicloud/aliyun/loadbalancer.go @@ -394,5 +394,5 @@ func (lb *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoad } func (lb *SLoadbalancer) GetProjectId() string { - return "" + return lb.ResourceGroupId } diff --git a/pkg/multicloud/aliyun/project.go b/pkg/multicloud/aliyun/project.go index 7d51533039..32e38f4609 100644 --- a/pkg/multicloud/aliyun/project.go +++ b/pkg/multicloud/aliyun/project.go @@ -14,9 +14,17 @@ package aliyun -import "time" +import ( + "fmt" + "time" + + "yunion.io/x/onecloud/pkg/multicloud" + "yunion.io/x/pkg/errors" +) + +type SResourceGroup struct { + multicloud.SResourceBase -type SProject struct { Status string AccountId string DisplayName string @@ -24,3 +32,43 @@ type SProject struct { CreateDate time.Time Name string } + +func (self *SResourceGroup) GetGlobalId() string { + return self.Id +} + +func (self *SResourceGroup) GetId() string { + return self.Id +} + +func (self *SResourceGroup) GetName() string { + return self.Name +} + +func (self *SResourceGroup) GetStatus() string { + return "" +} + +func (self *SAliyunClient) GetResourceGroups(pageNumber int, pageSize int) ([]SResourceGroup, int, error) { + if pageSize <= 0 || pageSize > 100 { + pageSize = 10 + } + if pageNumber <= 0 { + pageNumber = 1 + } + params := map[string]string{ + "PageNumber": fmt.Sprintf("%d", pageNumber), + "PageSize": fmt.Sprintf("%d", pageSize), + } + resp, err := self.rmRequest("ListResourceGroups", params) + if err != nil { + return nil, 0, errors.Wrap(err, "rmRequest.ListResourceGroups") + } + groups := []SResourceGroup{} + err = resp.Unmarshal(&groups, "ResourceGroups", "ResourceGroup") + if err != nil { + return nil, 0, errors.Wrap(err, "resp.Unmarshal") + } + total, _ := resp.Int("TotalCount") + return groups, int(total), nil +} diff --git a/pkg/multicloud/aliyun/shell/resourcegroup.go b/pkg/multicloud/aliyun/shell/resourcegroup.go new file mode 100644 index 0000000000..42deefc54c --- /dev/null +++ b/pkg/multicloud/aliyun/shell/resourcegroup.go @@ -0,0 +1,35 @@ +// 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 shell + +import ( + "yunion.io/x/onecloud/pkg/multicloud/aliyun" + "yunion.io/x/onecloud/pkg/util/shellutils" +) + +func init() { + type ResourceGroupListOptions struct { + PageSize int + PageNumber int + } + shellutils.R(&ResourceGroupListOptions{}, "resource-group-list", "List resource group", func(cli *aliyun.SRegion, args *ResourceGroupListOptions) error { + groups, _, err := cli.GetClient().GetResourceGroups(args.PageNumber, args.PageSize) + if err != nil { + return err + } + printList(groups, 0, 0, 0, nil) + return nil + }) +} diff --git a/pkg/multicloud/aliyun/snapshot.go b/pkg/multicloud/aliyun/snapshot.go index 65a9383d80..da7844785a 100644 --- a/pkg/multicloud/aliyun/snapshot.go +++ b/pkg/multicloud/aliyun/snapshot.go @@ -40,14 +40,15 @@ const ( type SSnapshot struct { region *SRegion - Progress string - SnapshotId string - SnapshotName string - SourceDiskId string - SourceDiskSize int32 - SourceDiskType string - Status SnapshotStatusType - Usage string + Progress string + SnapshotId string + SnapshotName string + SourceDiskId string + SourceDiskSize int32 + SourceDiskType string + Status SnapshotStatusType + Usage string + ResourceGroupId string } func (self *SSnapshot) GetId() string { @@ -200,7 +201,7 @@ func (self *SRegion) DeleteSnapshot(snapshotId string) error { } func (self *SSnapshot) GetProjectId() string { - return "" + return self.ResourceGroupId } // If snapshot linked images can't be delete diff --git a/pkg/multicloud/aliyun/vswitch.go b/pkg/multicloud/aliyun/vswitch.go index d09ca46af7..877066dd56 100644 --- a/pkg/multicloud/aliyun/vswitch.go +++ b/pkg/multicloud/aliyun/vswitch.go @@ -273,5 +273,5 @@ func (vsw *SVSwitch) dissociateWithSNAT() error { } func (self *SVSwitch) GetProjectId() string { - return "" + return self.ResourceGroupId }